mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-10 12:37:55 +01:00
fix(api-catalog): send an own MCP server's API key to the secure setup page
An agent asked to connect a person's own MCP server with an API key saw the connections_search instruction but kept searching the API for a way to create the connection itself. The two connection-creation entries it finds now say the person enters the key on Connect your own MCP server, and that the agent links that page and replies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c77024412d
commit
dc36aee6e1
2 files changed
+16
-3
No files matched your search
@@ -54,10 +54,10 @@ it("names only pages that the board UI mounts", () => {
|
||||
const appRoutes = readFileSync(path.join(repoRoot, "ui/src/App.tsx"), "utf8");
|
||||
const pages = new Set(
|
||||
runnerApiCatalog()
|
||||
.filter(row => /^\/api\/(mcp\/(setup|requests\/\{id\}\/consent)$|connection-intents\/|tool-connections\/\{connectionId\}\/(catalog|review-counts)$|companies\/\{companyId\}\/(tools\/apps\/attention|chat-endpoints)$)/.test(row.path))
|
||||
.filter(row => /^\/api\/(mcp\/(setup|requests\/\{id\}\/consent)$|connection-intents\/|tool-connections\/\{connectionId\}\/(catalog|review-counts)$|companies\/\{companyId\}\/(tools\/apps\/attention|tools\/apps\/connect|tools\/connections|chat-endpoints)$)/.test(row.path))
|
||||
.flatMap(row => [...(row.description ?? "").matchAll(/\/<prefix>\/([a-z0-9/<>-]+)/gi)].map(match => match[1]!)),
|
||||
);
|
||||
expect([...pages].sort()).toEqual(["apps/<connectionId>/permissions", "apps/assistant-connection", "company/settings/instance/experimental", "issues/<identifier>"]);
|
||||
expect([...pages].sort()).toEqual(["apps/<connectionId>/permissions", "apps/assistant-connection", "apps/byo", "company/settings/instance/experimental", "issues/<identifier>"]);
|
||||
const mounted = (page: string) => page
|
||||
.replace("apps/<connectionId>/permissions", "apps/:connectionId/:tab")
|
||||
.replace("issues/<identifier>", "issues/:issueId");
|
||||
@@ -65,6 +65,15 @@ it("names only pages that the board UI mounts", () => {
|
||||
expect(readFileSync(path.join(repoRoot, "ui/src/pages/apps/app-tabs.ts"), "utf8")).toContain("\"permissions\"");
|
||||
});
|
||||
|
||||
it.each([
|
||||
"connect custom MCP server with server URL and API key BYO connection",
|
||||
"byo custom mcp server create tool app connection",
|
||||
])("search %j sends an own-server API key to the secure page", (query) => {
|
||||
const found = searchRunnerApi({ query, limit: 10 }).results.filter(row => ["POST /api/companies/{companyId}/tools/apps/connect", "POST /api/companies/{companyId}/tools/connections"].includes(row.operationId));
|
||||
expect(found.length, query).toBeGreaterThan(0);
|
||||
for (const operation of found) expect(operation.description).toContain("[Connect your own MCP server](/<prefix>/apps/byo)");
|
||||
});
|
||||
|
||||
it("links only mounted pages from connections_search", () => {
|
||||
const appRoutes = readFileSync(path.join(repoRoot, "ui/src/App.tsx"), "utf8");
|
||||
const search = readFileSync(path.join(repoRoot, "server/src/services/connection-intents.ts"), "utf8");
|
||||
|
||||
@@ -11667,6 +11667,9 @@ registerCurrentRoute({
|
||||
"Inspect a curated app's public MCP and OAuth metadata without credentials or registration",
|
||||
});
|
||||
|
||||
const OWN_MCP_SERVER_KEY = "When a person's own MCP server needs an API key, the person adds it themselves on [Connect your own MCP server](/<prefix>/apps/byo): they enter its URL and type the key into that page's secure field. "
|
||||
+ "An agent cannot enter the key and must not ask for it in chat. Link that page and reply instead of creating the connection here.";
|
||||
|
||||
registerCurrentRoute({
|
||||
"x-paperclip-transport": "rest",
|
||||
"x-paperclip-connection-management": "connections:configure",
|
||||
@@ -11674,6 +11677,7 @@ registerCurrentRoute({
|
||||
path: "/api/companies/{companyId}/tools/apps/connect",
|
||||
tags: ["tool-access"],
|
||||
summary: "Create a draft app connection from gallery input",
|
||||
description: OWN_MCP_SERVER_KEY,
|
||||
body: connectToolAppSchema,
|
||||
responses: {
|
||||
200: r.ok(),
|
||||
@@ -11845,7 +11849,7 @@ registerCurrentRoute({
|
||||
path: "/api/companies/{companyId}/tools/connections",
|
||||
tags: ["tool-access"],
|
||||
summary: "Create a tool connection",
|
||||
description: "Saves a connection as given without checking that its server answers. To connect an MCP server from its URL, use POST /api/companies/{companyId}/tools/apps/connect with link instead: it checks the server first, and a fresh setup saves nothing when the server cannot be reached.",
|
||||
description: "Saves a connection as given without checking that its server answers. To connect an MCP server from its URL, use POST /api/companies/{companyId}/tools/apps/connect with link instead: it checks the server first, and a fresh setup saves nothing when the server cannot be reached." + " " + OWN_MCP_SERVER_KEY,
|
||||
body: createToolConnectionSchema,
|
||||
responses: {
|
||||
201: r.ok(),
|
||||
|
||||
Reference in new issue
Block a user