Emdash source with visual editor image upload fix
Fixes: 1. media.ts: wrap placeholder generation in try-catch 2. toolbar.ts: check r.ok, display error message in popover
This commit is contained in:
86
docs/src/worker.ts
Normal file
86
docs/src/worker.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { handle } from "@astrojs/cloudflare/handler";
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { createMcpHandler } from "agents/mcp";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
* Build a fresh McpServer per request. createMcpHandler is stateless, and the
|
||||
* underlying transport asserts that the server is not already connected, so we
|
||||
* cannot reuse a single server instance across requests.
|
||||
*/
|
||||
function buildMcpServer(env: Env): McpServer {
|
||||
const server = new McpServer({
|
||||
name: "emdash-docs",
|
||||
version: "1.0.0",
|
||||
});
|
||||
|
||||
server.registerTool(
|
||||
"search_docs",
|
||||
{
|
||||
title: "Search EmDash documentation",
|
||||
description:
|
||||
"Search the EmDash CMS documentation. Returns relevant chunks with source URLs and similarity scores.",
|
||||
inputSchema: {
|
||||
query: z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(1000)
|
||||
.describe("Natural-language query against the EmDash docs."),
|
||||
max_results: z
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(20)
|
||||
.optional()
|
||||
.describe("Maximum number of chunks to return. Defaults to 8."),
|
||||
},
|
||||
},
|
||||
async ({ query, max_results }) => {
|
||||
const limit = max_results ?? 8;
|
||||
|
||||
const results = await env.AI_SEARCH.search({
|
||||
messages: [{ role: "user", content: query }],
|
||||
ai_search_options: {
|
||||
retrieval: { max_num_results: limit },
|
||||
},
|
||||
});
|
||||
|
||||
if (!results.chunks.length) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "No matching docs found.",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
content: results.chunks.map((chunk) => {
|
||||
const source = chunk.item.key;
|
||||
const score = typeof chunk.score === "number" ? chunk.score.toFixed(3) : "n/a";
|
||||
return {
|
||||
type: "text" as const,
|
||||
text: `<result source="${source}" score="${score}">\n${chunk.text}\n</result>`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
||||
const url = new URL(request.url);
|
||||
|
||||
if (url.pathname === "/mcp") {
|
||||
const handler = createMcpHandler(buildMcpServer(env), { route: "/mcp" });
|
||||
return handler(request, env, ctx);
|
||||
}
|
||||
|
||||
return handle(request, env, ctx);
|
||||
},
|
||||
} satisfies ExportedHandler<Env>;
|
||||
Reference in New Issue
Block a user