instructions: name the developer index in the full profile

The full-profile MCP instructions omitted the developer index entirely,
while the search-only profile already described it. Add one capability
sentence naming firecrawl_developer_search (and the categories
fallback). The keyless profile is left unchanged: its instruction text
stays scoped to the keyless tool surface (Search, Scrape, Parse).

Also extend the metadata-policy test gates to the full, keyless, and
account profile instructions, so future rewrites of these constants
into routing playbooks fail in CI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Himadri Mishra
2026-08-20 21:41:11 +05:30
committed by Karan Lokchandani
parent a96250d21c
commit e8484dfa0a
2 changed files with 44 additions and 1 deletions
+1 -1
View File
@@ -884,7 +884,7 @@ const openAiAppsChallengeToken = normalizeHeader(
process.env.OPENAI_APPS_CHALLENGE_TOKEN
);
const FULL_PROFILE_INSTRUCTIONS = `Firecrawl provides web search, page retrieval, site URL discovery, multi-page collection, structured page data, monitoring, and asynchronous research. Match the requested operation to the tool boundary: firecrawl_scrape retrieves one supplied page and can return JSON matching a supplied schema, firecrawl_map enumerates URLs under a site without retrieving their content, and firecrawl_agent starts multi-source research whose result is read with firecrawl_agent_status. For biomedical, life-science, clinical, or arXiv literature, the firecrawl_research_* tools search a paper index of abstracts and full text; firecrawl_search with categories: ["research"] is a website filter over ordinary web results and reaches different sources. Provide only the required inputs and account for stated network or external side effects.`;
const FULL_PROFILE_INSTRUCTIONS = `Firecrawl provides web search, page retrieval, site URL discovery, multi-page collection, structured page data, monitoring, and asynchronous research. Match the requested operation to the tool boundary: firecrawl_scrape retrieves one supplied page and can return JSON matching a supplied schema, firecrawl_map enumerates URLs under a site without retrieving their content, and firecrawl_agent starts multi-source research whose result is read with firecrawl_agent_status. For biomedical, life-science, clinical, or arXiv literature, the firecrawl_research_* tools search a paper index of abstracts and full text; firecrawl_search with categories: ["research"] is a website filter over ordinary web results and reaches different sources. For a programming question — code behaviour, a library or framework, an API contract, an error message, or a known bug — firecrawl_developer_search (or firecrawl_search with categories: ["developer"]) searches an index of GitHub issues, merged pull requests, READMEs, and curated documentation sites. Provide only the required inputs and account for stated network or external side effects.`;
const KEYLESS_PROFILE_INSTRUCTIONS = `Without authentication, this endpoint exposes Search, Scrape, and Parse with usage limits. An OAuth connection or Authorization bearer API key exposes account tools; unavailable tools return connection guidance. Firecrawl provides web search, page retrieval, site URL discovery, multi-page collection, structured page data, monitoring, and asynchronous research. Match the requested operation to the tool boundary: firecrawl_scrape retrieves one supplied page and can return JSON matching a supplied schema, firecrawl_map enumerates URLs under a site without retrieving their content, and firecrawl_agent starts multi-source research whose result is read with firecrawl_agent_status. For biomedical, life-science, clinical, or arXiv literature, firecrawl_search with categories: ["research"] filters ordinary web results to research-affiliated websites; the firecrawl_research_* tools search a separate paper index of abstracts and full text and become available once an OAuth connection or Authorization bearer API key is present. Provide only the required inputs.`;
// The search surface exposes web/research search only. Its instructions and tool
+43
View File
@@ -751,6 +751,49 @@ test('primary search profile agent language satisfies metadata policy gates', as
);
});
test('keyless full-surface instructions satisfy the same metadata policy gates', async (t) => {
// FASTMCP_ENDPOINT '/v2/mcp' (not '/v2/mcp-oauth') makes this the keyless
// profile, whose instructions must stay descriptive rather than becoming an
// imperative routing playbook.
const { fullPort } = await startHostedServer(t);
const headers = { 'x-api-key': 'fc-keyless-metadata' };
const initialize = await initializeProfile(fullPort, '/v2/mcp', headers);
const tools = await listToolDefinitions(fullPort, '/v2/mcp', headers);
assertAgentMetadataPolicy(
[initialize.instructions, ...tools.map((tool) => tool.description ?? '')],
assert
);
});
test('account (mcp-oauth) full-surface instructions satisfy the same metadata policy gates', async (t) => {
const accountResource = 'https://mcp.firecrawl.dev/v2/mcp-oauth';
const backend = await startFakeBackend({ introspectionAud: accountResource });
t.after(() => backend.close());
const port = await getFreePort();
const child = spawnServer({
CLOUD_SERVICE: 'true',
HTTP_STREAMABLE_SERVER: 'true',
FASTMCP_ENDPOINT: '/v2/mcp-oauth',
FIRECRAWL_API_URL: backend.url,
FIRECRAWL_MCP_RESOURCE_URL: accountResource,
FIRECRAWL_OAUTH_ISSUER: backend.url,
FIRECRAWL_OAUTH_INTROSPECT_SECRET: 'test-secret',
PORT: String(port),
});
t.after(() => stopChild(child));
await waitForHealth(port, child);
const headers = { authorization: 'Bearer fco_account_metadata' };
const initialize = await initializeProfile(port, '/v2/mcp-oauth', headers);
const tools = await listToolDefinitions(port, '/v2/mcp-oauth', headers);
assertAgentMetadataPolicy(
[initialize.instructions, ...tools.map((tool) => tool.description ?? '')],
assert
);
});
test('primary search profile fails closed unless the canonical OAuth-only flag is enabled', async (t) => {
const port = await getFreePort();
const child = spawnServer({