# How Craft Agents Integrate with External MCP Servers and REST APIs

> Learn how Craft Agents integrate external MCP servers and REST APIs with its declarative Source abstraction. Automatically configure callable tools for the Claude Agent SDK.

- Repository: [Craft Ai Agents/craft-agents-oss](https://github.com/craft-ai-agents/craft-agents-oss)
- Tags: how-to-guide
- Published: 2026-07-04

---

**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`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/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`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/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:

```typescript
// 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:

```typescript
// 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`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/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`:

```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

```json
{
  "type": "api",
  "slug": "google-calendar",
  "provider": "google",
  "api": {
    "baseUrl": "https://www.googleapis.com/calendar/v3",
    "authType": "bearer"
  }
}

```

### Building Servers with SourceServerBuilder

```typescript
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

```typescript
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`, and `local`.
- **`SourceServerBuilder`** ([`packages/shared/src/sources/server-builder.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/sources/server-builder.ts)) constructs server configurations via `buildMcpServer` for MCP connections and `buildApiServer` for 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`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/config.json) file, with schemas defined in [`packages/shared/src/sources/types.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/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.