Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions mcp/.dev.vars.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Uncomment and point at a self-hosted Honcho to bypass the managed API.
# wrangler dev reads this file automatically when it exists as `.dev.vars`.
# For deployed Workers, use: wrangler secret put HONCHO_API_URL
# HONCHO_API_URL=http://127.0.0.1:28000
1 change: 1 addition & 0 deletions mcp/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dist/
.env
.env.local
.env.production
.dev.vars

# IDE files
.vscode/
Expand Down
22 changes: 22 additions & 0 deletions mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,28 @@ Built on:
- **[@modelcontextprotocol/sdk](https://www.npmjs.com/package/@modelcontextprotocol/sdk)** — `McpServer` for tool registration
- **[@honcho-ai/sdk](https://www.npmjs.com/package/@honcho-ai/sdk)** v2 — Honcho TypeScript SDK

## Self-Hosted Honcho

If you run Honcho yourself (for privacy, latency, or offline use), deploy the
MCP Worker alongside your instance and set `HONCHO_API_URL` in its
environment.

**Local dev (`bun run dev`):** create `mcp/.dev.vars`:

```
HONCHO_API_URL=http://127.0.0.1:28000
```

**Deployed Worker:**

```bash
wrangler secret put HONCHO_API_URL
# paste your URL when prompted
```

When `HONCHO_API_URL` is unset the Worker routes to `https://api.honcho.dev`,
so this change is backward-compatible.

## Development

### Setup
Expand Down
16 changes: 13 additions & 3 deletions mcp/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,21 @@ export interface HonchoConfig {
workspaceId: string;
}

export interface Env {
HONCHO_API_URL?: string;
}

/**
* Parse configuration from request headers.
* Parse configuration from request headers and Worker env bindings.
* Throws on missing required fields so callers get clear errors.
*
* The Honcho API URL is read from the `HONCHO_API_URL` env var when set,
* allowing operators to run this Worker alongside a self-hosted Honcho
* instance (see the "Self-Hosted Honcho" section in README.md). It is
* intentionally not exposed as a request header: routing public requests
* to an internal URL would be a latency and security regression.
*/
export function parseConfig(request: Request): HonchoConfig {
export function parseConfig(request: Request, env: Env = {}): HonchoConfig {
const authHeader = request.headers.get("Authorization");
const trimmedAuthHeader = authHeader?.trim();
if (!trimmedAuthHeader?.startsWith("Bearer ")) {
Expand All @@ -37,7 +47,7 @@ export function parseConfig(request: Request): HonchoConfig {
apiKey,
userName,
assistantName: request.headers.get("X-Honcho-Assistant-Name")?.trim() || "Assistant",
baseUrl: "https://api.honcho.dev",
baseUrl: env.HONCHO_API_URL?.trim() || "https://api.honcho.dev",
workspaceId: request.headers.get("X-Honcho-Workspace-ID")?.trim() || "default",
};
}
Expand Down
6 changes: 3 additions & 3 deletions mcp/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createMcpHandler } from "agents/mcp";
import { parseConfig, createClient } from "./config.js";
import { parseConfig, createClient, type Env } from "./config.js";
import { createServer } from "./server.js";

const CORS_ORIGIN = "*";
Expand All @@ -16,7 +16,7 @@ const CORS_HEADERS = {
export default {
async fetch(
request: Request,
env: unknown,
env: Env,
executionCtx: ExecutionContext,
): Promise<Response> {
if (request.method === "OPTIONS") {
Expand All @@ -25,7 +25,7 @@ export default {

let config;
try {
config = parseConfig(request);
config = parseConfig(request, env);
} catch (e) {
const message =
e instanceof Error ? e.message : "Invalid request";
Expand Down
Loading