How Craft Agents Integrate with External MCP Servers and REST APIs
Craft Agents unifies external service integration through a declarative "Source" abstraction that automatically configures MCP servers and REST APIs as callable tools for the Claude Agent SDK.
Craft Agents provides a seamless bridge between AI agents and external services by treating every connection as a configurable Source. According to the craft-ai-agents/craft-agents-oss source code, the platform supports both MCP (Model Context Protocol) servers and traditional REST APIs through a unified configuration system stored in workspace-specific JSON files.
The Source Abstraction: Declarative Configuration
Every external connection in Craft Agents is defined as a Source—a declarative JSON configuration stored under a workspace's sources/ folder. The SourceType enum in packages/shared/src/sources/types.ts defines three possible types: mcp, api, or local.
When the runtime initializes, the SourceServerBuilder class (packages/shared/src/sources/server-builder.ts) iterates over all enabled sources and validates them using the isSourceUsable helper before constructing the appropriate server configuration.
MCP Server Integration
MCP servers expose remote or local service capabilities to the Claude Agent SDK. A source's config.mcp block defines the transport mechanism, URL, authentication, and headers.
Remote HTTP and SSE Transport
For remote servers, the buildMcpServer method normalizes the URL and merges three layers of headers:
// In SourceServerBuilder
buildMcpServer(source: LoadedSource, token: string | null,
credential?: ApiCredential | null): McpServerConfig | null
The builder calls normalizeMcpUrl to standardize endpoints, then combines static config headers, credential-store headers, and bearer tokens (for OAuth/Bearer authentication). The resulting configuration matches the shape expected by createSdkMcpServer from the Claude Agent SDK.
Local Stdio Transport
For development or on-device agents, the builder supports stdio transport. When configured, buildMcpServer returns a configuration containing the command, arguments, and environment variables, enabling the SDK to spawn a subprocess and communicate via stdin/stdout.
All MCP configurations are collected in a mcpServers map keyed by source slug, which the agent passes to the Claude SDK. Tool calls like mcp__my-server__my-tool route to the correct endpoint based on this mapping.
REST API Integration
API sources (type: 'api') use a config.api block containing baseUrl, authType, and optionally a provider (e.g., google, slack, microsoft). The builder creates in-process API servers via the buildApiServer method:
// In SourceServerBuilder
async buildApiServer(
source: LoadedSource,
credential: ApiCredential | null,
getToken?: () => Promise<string>,
sessionPath?: string,
summarize?: SummarizeCallback,
getCredential?: () => Promise<ApiCredential | null>
): Promise<ReturnType<typeof createSdkMcpServer> | null>
OAuth and Authentication Handling
For OAuth-based providers (Google, Slack, Microsoft), the builder checks source.config.isAuthenticated and supplies a getToken callback that automatically refreshes OAuth tokens. For header- or query-based authentication, the builder injects credentials from the credential argument into the request configuration.
The resulting API server is stored in an apiServers map (keyed by source slug) and exposed as a tool to the agent. When a tool invokes a REST endpoint, the in-process server forwards the request, adds proper auth headers, and handles pagination according to the SDK's networking layer.
Unified Tool Access and Routing
Both MCP and API servers become tool descriptors that Claude can call. The UnifiedNetworkInterceptor (packages/shared/src/unified-network-interceptor.ts) guarantees that every tool receives consistent metadata (such as OpenAPI schemas) regardless of whether it originates from an MCP server or a REST API.
Tool names follow specific patterns:
- MCP tools:
mcp__<slug>__<tool> - API tools:
<slug>_api.<endpoint>
Configuration Examples
Defining an MCP Source
Create a JSON file at ~/.craft-agent/workspaces/<id>/sources/<slug>/config.json:
{
"type": "mcp",
"slug": "my-mcp",
"mcp": {
"transport": "http",
"url": "https://example.com/mcp",
"authType": "bearer",
"headers": {
"X-Custom-Header": "my-value"
}
}
}
Defining a REST API Source
{
"type": "api",
"slug": "google-calendar",
"provider": "google",
"api": {
"baseUrl": "https://www.googleapis.com/calendar/v3",
"authType": "bearer"
}
}
Building Servers with SourceServerBuilder
import { SourceServerBuilder } from '@craft-agents/shared/sources/server-builder';
import { readSources } from '@craft-agents/shared/sources/storage'; // pseudo-helper
async function initialise() {
const sources = await readSources(); // returns LoadedSource[]
const builder = new SourceServerBuilder();
const result = await builder.buildAll(
sources.map(s => ({
source: s,
token: s.config.type === 'mcp' ? s.sessionToken : undefined,
credential: s.credential,
}))
);
// result.mcpServers and result.apiServers are now ready for the Claude SDK
console.log('MCP servers:', result.mcpServers);
console.log('API servers:', result.apiServers);
}
Using Tools in Agent Workflows
await agent.runPlan({
plan: [
{ tool: 'mcp__my-mcp__list_items', input: {} },
{ tool: 'google-calendar_api.list_events', input: { calendarId: 'primary' } }
]
});
The SDK resolves each tool to the server created earlier, automatically applying merged authentication headers and handling response streaming.
Summary
- Sources are declarative JSON configurations stored in workspace
sources/folders, supporting three types:mcp,api, andlocal. SourceServerBuilder(packages/shared/src/sources/server-builder.ts) constructs server configurations viabuildMcpServerfor MCP connections andbuildApiServerfor REST APIs.- Authentication is handled automatically through token getters for OAuth providers and credential injection for header-based auth.
- Unified access is ensured by the
UnifiedNetworkInterceptor, providing consistent metadata for both MCP and API tools. - Tool routing uses namespaced identifiers (
mcp__<slug>__<tool>or<slug>_api.<endpoint>) to route calls to the correct server.
Frequently Asked Questions
What file format does Craft Agents use to configure external services?
Craft Agents uses declarative JSON files stored under each workspace's sources/ directory. Each source defines its type, authentication parameters, and connection details in a config.json file, with schemas defined in packages/shared/src/sources/types.ts.
How does Craft Agents handle authentication for external APIs?
The SourceServerBuilder automatically manages OAuth token refresh for providers like Google, Slack, and Microsoft through the getToken callback. For services using header or query-based authentication, it merges static headers from the source configuration with runtime credentials from the credential store.
Can Craft Agents connect to local MCP servers running on my machine?
Yes. When a source specifies transport: "stdio", the buildMcpServer method returns a stdio configuration containing the command, arguments, and environment variables. This enables the Claude Agent SDK to spawn and communicate with local subprocesses via stdin/stdout.
Where are the MCP and API server configurations stored at runtime?
The SourceServerBuilder aggregates configurations into two maps: mcpServers and apiServers, both keyed by source slug. These maps are passed directly to the Claude Agent SDK, which registers tools like mcp__my-server__my-tool or google-calendar_api.list_events for use during chat sessions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →