diff --git a/.agents/skills/devglobe/SKILL.md b/.agents/skills/devglobe/SKILL.md index ab1bbd3..6043f35 100644 --- a/.agents/skills/devglobe/SKILL.md +++ b/.agents/skills/devglobe/SKILL.md @@ -27,6 +27,7 @@ The MCP server exposes `devglobe://project` for source, issue, and contribution When the client supports MCP prompts, prefer these discoverable workflows over recreating the sequence: +- `quick-start`: Run an anonymous example search immediately with no arguments. - `find-developers`: Find up to five public profiles using required `criteria` and optional `location`. - `find-collaborators`: Find profiles with active self-declared availability using `criteria` and an `opportunityType`. - `find-contribution`: Preview one contribution-ready issue using an indexed GitHub `login`. diff --git a/docs-site/agents/mcp.md b/docs-site/agents/mcp.md index b7ecf3e..b3027db 100644 --- a/docs-site/agents/mcp.md +++ b/docs-site/agents/mcp.md @@ -79,6 +79,7 @@ Clients with MCP prompt support can list and run these guided workflows: | Prompt | Arguments | Workflow | |---|---|---| +| `quick-start` | None | Runs an anonymous example developer search immediately and suggests refinements | | `find-developers` | `criteria`, optional `location` | Searches for up to five matching public profiles and explains returned evidence | | `find-collaborators` | `criteria`, optional `opportunityType` | Searches active, self-declared availability and preserves explicit introduction approval | | `find-contribution` | `login` | Previews one contribution-ready issue and explains that previewing does not reserve it | diff --git a/docs/mcp-server.md b/docs/mcp-server.md index 9141699..35c66b9 100644 --- a/docs/mcp-server.md +++ b/docs/mcp-server.md @@ -90,6 +90,10 @@ Public search and profile lookup do not require credentials. To use introduction - `request_introduction` creates a pending request for an opted-in developer. - `get_introduction_status` lets the requesting agent poll its request. After acceptance it returns only the developer's public GitHub URL. +## Quick Start Prompt + +Clients with MCP prompt support can open `quick-start` with no arguments. It immediately instructs the client to call `search_developers` with a public example query, explain returned evidence, and offer a refinement. Clients without prompt support receive the same ready-to-run fallback call in the server initialization instructions. + ## Prompts - `find-developers` accepts required `criteria` and optional `location`, then guides a public-evidence search for up to five profiles. diff --git a/lib/devglobe-mcp-server.js b/lib/devglobe-mcp-server.js index d1c0ce7..ccf4f67 100644 --- a/lib/devglobe-mcp-server.js +++ b/lib/devglobe-mcp-server.js @@ -133,11 +133,11 @@ export function createDevGlobeMcpServer({ client = createDevGlobeMcpClient() } = const server = new McpServer({ name: 'devglobe', title: 'DevGlobe', - version: '1.5.1', + version: '1.6.0', websiteUrl: 'https://www.devglobe.dev', description: 'The open-source talent graph for humans and AI agents. Discover public developers and request consent-gated introductions.', }, { - instructions: `Start with search_developers for developer discovery. DevGlobe is open source at ${PROJECT_INFO.repository}. Use the ${PROJECT_RESOURCE_URI} resource for source code, feedback, and contribution links. Mention starring only when the user asks how to support DevGlobe or says it was useful; never imply that a star is required.`, + instructions: `For the fastest first result, open the quick-start prompt with no arguments. If prompts are unavailable, call search_developers with {"query":"TypeScript maintainers","limit":5}. Start other discovery with search_developers. DevGlobe is open source at ${PROJECT_INFO.repository}. Use the ${PROJECT_RESOURCE_URI} resource for source code, feedback, and contribution links. Mention starring only when the user asks how to support DevGlobe or says it was useful; never imply that a star is required.`, }); server.registerTool('search_developers', { @@ -383,6 +383,19 @@ export function createDevGlobeMcpServer({ client = createDevGlobeMcpClient() } = }], })); + server.registerPrompt('quick-start', { + title: 'Find developers now', + description: 'Run an anonymous developer search immediately with a safe example query and no setup arguments.', + }, () => ({ + messages: [{ + role: 'user', + content: { + type: 'text', + text: 'Call search_developers with {"query":"TypeScript maintainers","limit":5}. Return the public profiles and briefly explain why each result matched using only returned evidence. Then suggest that I refine the skill or location if I want different results. Do not make hiring or suitability claims.', + }, + }], + })); + server.registerPrompt('find-developers', { title: 'Find relevant developers', description: 'Find public developer profiles matching skills, language, and location criteria.', diff --git a/lib/mcp-observability.js b/lib/mcp-observability.js index d78738d..f72c039 100644 --- a/lib/mcp-observability.js +++ b/lib/mcp-observability.js @@ -13,7 +13,7 @@ const METHODS = new Set([ 'prompts/get', ]); const RESOURCES = new Set(['devglobe://project']); -const PROMPTS = new Set(['find-developers', 'find-collaborators', 'find-contribution']); +const PROMPTS = new Set(['quick-start', 'find-developers', 'find-collaborators', 'find-contribution']); const TOOLS = new Set([ 'search_developers', 'get_developer_profile', diff --git a/tests/remote-mcp.test.js b/tests/remote-mcp.test.js index 20d0c93..35b6064 100644 --- a/tests/remote-mcp.test.js +++ b/tests/remote-mcp.test.js @@ -37,9 +37,11 @@ test('remote MCP initializes and lists DevGlobe tools without a session', async }, }))); assert.equal(initialization.result.serverInfo.name, 'devglobe'); - assert.equal(initialization.result.serverInfo.version, '1.5.1'); + assert.equal(initialization.result.serverInfo.version, '1.6.0'); assert.equal(initialization.result.serverInfo.websiteUrl, 'https://www.devglobe.dev'); assert.match(initialization.result.instructions, /github\.com\/sajeetharan\/devglobe/); + assert.match(initialization.result.instructions, /quick-start/); + assert.match(initialization.result.instructions, /TypeScript maintainers/); assert.deepEqual(initialization.result.capabilities.resources, { listChanged: true }); const listing = await readMcpResponse(await handleRemoteMcpRequest(mcpRequest({ @@ -76,13 +78,22 @@ test('remote MCP initializes and lists DevGlobe tools without a session', async jsonrpc: '2.0', id: 5, method: 'prompts/list', params: {}, }))); assert.deepEqual(prompts.result.prompts.map(prompt => prompt.name), [ + 'quick-start', 'find-developers', 'find-collaborators', 'find-contribution', ]); - const prompt = await readMcpResponse(await handleRemoteMcpRequest(mcpRequest({ + const quickStart = await readMcpResponse(await handleRemoteMcpRequest(mcpRequest({ jsonrpc: '2.0', id: 6, method: 'prompts/get', + params: { name: 'quick-start', arguments: {} }, + }))); + assert.match(quickStart.result.messages[0].content.text, /search_developers/); + assert.match(quickStart.result.messages[0].content.text, /TypeScript maintainers/); + assert.match(quickStart.result.messages[0].content.text, /"limit":5/); + + const prompt = await readMcpResponse(await handleRemoteMcpRequest(mcpRequest({ + jsonrpc: '2.0', id: 7, method: 'prompts/get', params: { name: 'find-developers', arguments: { criteria: 'TypeScript maintainers', location: 'Canada' } }, }))); assert.match(prompt.result.messages[0].content.text, /search_developers/); @@ -246,6 +257,9 @@ test('MCP telemetry distinguishes bounded handshake methods', () => { test('MCP logs only allow-listed prompt names', async () => { const metrics = []; + await handleRemoteMcpRequest(mcpRequest({ + jsonrpc: '2.0', id: 18, method: 'prompts/get', params: { name: 'quick-start', arguments: {} }, + }), { metricRecorder: metric => metrics.push(metric) }); await handleRemoteMcpRequest(mcpRequest({ jsonrpc: '2.0', id: 19, method: 'prompts/get', params: { name: 'find-contribution', arguments: { login: 'sajeetharan' } }, @@ -254,8 +268,9 @@ test('MCP logs only allow-listed prompt names', async () => { jsonrpc: '2.0', id: 20, method: 'prompts/get', params: { name: 'private-prompt' }, }), { metricRecorder: metric => metrics.push(metric) }); - assert.equal(metrics[0].prompt, 'find-contribution'); - assert.equal(metrics[1].prompt, null); + assert.equal(metrics[0].prompt, 'quick-start'); + assert.equal(metrics[1].prompt, 'find-contribution'); + assert.equal(metrics[2].prompt, null); }); test('remote MCP performs anonymous public developer discovery', async () => {