A source is a unit of tool registration. Toolshed supports four source types, each with its own adapter that resolves a configuration into a set of tools.
Source types
OpenAPI
Fetches an OpenAPI/Swagger specification and auto-generates tools from each endpoint.
{
"type": "openapi",
"id": "billing-api",
"namespace": "billing",
"specUrl": "https://api.example.com/openapi.json",
"auth": { "type": "bearer", "envVar": "BILLING_API_KEY" },
"baseUrl": "https://api.example.com",
"operationFilter": null
}
| Field | Type | Required | Description |
|---|
type | "openapi" | Yes | Source type |
id | string | Yes | Unique source ID |
namespace | string | Yes | Tool path prefix |
specUrl | string | Yes | URL to the OpenAPI spec |
auth | SourceAuth | No | Authentication config |
baseUrl | string | No | Override base URL |
operationFilter | function | No | ({ method, path, operationId? }) => boolean |
Tool path generation: namespace.resource.action (e.g., billing.invoices.list).
Action is derived from HTTP method: GET -> list/get, POST -> create, PUT -> update, PATCH -> patch, DELETE -> delete.
Destructiveness: Derived from HTTP method. GET, HEAD, OPTIONS are safe; all others are destructive.
GraphQL
Introspects a GraphQL schema and generates tools from queries and mutations.
{
"type": "graphql",
"id": "cms-api",
"namespace": "cms",
"endpoint": "https://api.example.com/graphql",
"auth": { "type": "bearer", "envVar": "CMS_API_KEY" },
"headers": { "X-Custom": "value" }
}
| Field | Type | Required | Description |
|---|
type | "graphql" | Yes | Source type |
id | string | Yes | Unique source ID |
namespace | string | Yes | Tool path prefix |
endpoint | string | Yes | GraphQL endpoint URL |
auth | SourceAuth | No | Authentication config |
headers | object | No | Additional HTTP headers |
operationFilter | function | No | ({ name, type }) => boolean where type is "query" or "mutation" |
Tool path generation: namespace.field_name (camelCase converted to snake_case).
Destructiveness: Queries are safe, mutations are destructive.
MCP
Connects to an external MCP server and imports its tools.
{
"type": "mcp",
"id": "external-tools",
"namespace": "external",
"transport": {
"type": "http",
"url": "https://mcp.example.com",
"headers": { "Authorization": "Bearer token" }
}
}
| Field | Type | Required | Description |
|---|
type | "mcp" | Yes | Source type |
id | string | Yes | Unique source ID |
namespace | string | Yes | Tool path prefix |
transport | object | Yes | { type: "http", url, headers? } or { type: "stdio", command, args?, env? } |
auth | SourceAuth | No | Authentication config |
Tool path generation: namespace.tool_name (spaces and non-alphanumeric characters converted to underscores).
Destructiveness: Reads annotations.destructiveHint from MCP tool metadata.
Stdio transport is defined in the config schema but not yet implemented in the adapter.
Plugin
Wraps a hand-written definePlugin() result as a source for registry consistency.
{
"type": "plugin",
"id": "github",
"namespace": "github",
"pluginId": "github"
}
| Field | Type | Required | Description |
|---|
type | "plugin" | Yes | Source type |
id | string | Yes | Unique source ID |
namespace | string | Yes | Tool path prefix |
pluginId | string | Yes | ID of the plugin to wrap |
Authentication types
The auth field supports four types:
| Type | Fields | Description |
|---|
oauth2 | provider, scopes? | OAuth2 via Toolshed’s token vending |
api_key | header, envVar? | API key sent as a custom header |
bearer | envVar? | Bearer token from environment variable |
none | — | No authentication needed |
Registering via API
curl -X POST http://localhost:3000/api/registry/sources \
-H "Authorization: Bearer $TOOLSHED_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"type": "openapi",
"id": "petstore",
"namespace": "petstore",
"specUrl": "https://petstore3.swagger.io/api/v3/openapi.json"
}'
The server validates the config against SourceConfigSchema, calls resolveSource() to fetch and parse the spec, and registers all discovered tools in the catalog.