getSpecFile
Retrieve the contents of a file from an API specification by providing the specification ID and file path.
Instructions
Gets the contents of an API specification's file.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| specId | Yes | The spec's ID. | |
| filePath | Yes | The path to the file. |
Implementation Reference
- src/tools/getSpecFile.ts:19-45 (handler)Handler function that executes the getSpecFile tool logic. It makes a GET request to the Postman API endpoint `/specs/{specId}/files/{filePath}` to retrieve the contents of an API specification file. Returns the result as text content.
export async function handler( args: z.infer<typeof parameters>, extra: { client: PostmanAPIClient; headers?: IsomorphicHeaders; serverContext?: ServerContext } ): Promise<CallToolResult> { try { const endpoint = `/specs/${args.specId}/files/${args.filePath}`; const query = new URLSearchParams(); const url = query.toString() ? `${endpoint}?${query.toString()}` : endpoint; const options: any = { headers: extra.headers, }; const result = await extra.client.get(url, options); return { content: [ { type: 'text', text: `${typeof result === 'string' ? result : JSON.stringify(result, null, 2)}`, }, ], }; } catch (e: unknown) { if (e instanceof McpError) { throw e; } throw asMcpError(e); } } - src/tools/getSpecFile.ts:8-11 (schema)Input validation schema using Zod. Accepts `specId` (the spec's ID) and `filePath` (the path to the file) as required string parameters.
export const parameters = z.object({ specId: z.string().describe("The spec's ID."), filePath: z.string().describe('The path to the file.'), }); - src/enabledResources.ts:104-261 (registration)Tool registered in the 'full' tools list (line 104) and the 'minimal' tools list (line 184) of enabledResources, which controls which tools are loaded by the server.
'getSpecFile', 'getSpecFiles', 'updateSpecFile', // Workspaces 'createWorkspace', 'deleteWorkspace', 'getWorkspace', 'getWorkspaces', 'updateWorkspace', 'getWorkspaceGlobalVariables', 'updateWorkspaceGlobalVariables', 'getWorkspaceTags', 'updateWorkspaceTags', // PAN (Private API Network) 'listPrivateNetworkWorkspaces', 'listPrivateNetworkAddRequests', 'removeWorkspaceFromPrivateNetwork', 'addWorkspaceToPrivateNetwork', 'respondPrivateNetworkAddRequest', // // Documentation 'publishDocumentation', 'unpublishDocumentation', // Tasks and Status 'getAsyncSpecTaskStatus', 'getStatusOfAnAsyncApiTask', // User and Tags 'getAuthenticatedUser', 'getTaggedEntities', // Code Generation 'getCodeGenerationInstructions', // Transfer 'transferCollectionFolders', 'transferCollectionResponses', 'transferCollectionResponses', // 'asyncMergePullCollectionFork' skipped // 'asyncMergePullCollectionTaskStatus' skipped // Duplicate Collection 'duplicateCollection', 'getDuplicateCollectionTaskStatus', 'deleteApiCollectionComment', 'deleteSpecFile', 'getEnabledTools', 'searchPostmanElementsInPublicNetwork', 'searchPostmanElementsInPrivateNetwork', // Analytics 'getAnalyticsData', 'getAnalyticsMetadata', ] as const; const minimal = [ 'createCollection', 'createEnvironment', 'createMock', 'createSpec', 'createSpecFile', 'createWorkspace', 'generateCollection', 'generateSpecFromCollection', 'getAllSpecs', 'getAuthenticatedUser', 'getCollection', 'getCollections', 'getEnvironment', 'getEnvironments', 'getGeneratedCollectionSpecs', 'getMock', 'getMocks', 'getSpec', 'getSpecCollections', 'getSpecDefinition', 'getSpecFile', 'getSpecFiles', 'getTaggedEntities', 'getWorkspace', 'getWorkspaces', 'publishMock', 'putCollection', 'putEnvironment', 'syncCollectionWithSpec', 'syncSpecWithCollection', 'updateMock', 'updateSpecFile', 'updateSpecProperties', 'updateWorkspace', 'createCollectionRequest', 'createCollectionResponse', 'duplicateCollection', 'getDuplicateCollectionTaskStatus', 'runCollection', 'getEnabledTools', 'updateCollectionRequest', ] as const; const code = [ 'getCodeGenerationInstructions', 'getWorkspace', 'getWorkspaces', 'searchPostmanElementsInPublicNetwork', 'getCollectionRequest', 'getCollectionResponse', 'getCollectionFolder', 'getAuthenticatedUser', 'getCollection', 'getEnvironment', 'getEnvironments', 'searchPostmanElementsInPrivateNetwork', ] as const; const excludedFromGeneration = [ 'runCollection', 'getEnabledTools', 'getCodeGenerationInstructions', 'getCollectionMap', 'getCollection', 'searchPostmanElementsInPublicNetwork', 'searchPostmanElementsInPrivateNetwork', ] as const; /** * Subtools are tools that are grouped under a parent tool orchestrator. * Each subtool is defined with: * - orchestrator: The main tool that will be exposed (the index.ts file) * - subtools: Array of tools that will be placed in the orchestrator's folder * * Example structure for 'getCollection': * tools/ * getCollection/ * index.ts <- orchestrator (handles routing logic) * getCollection.ts <- subtool (the actual API call) * getCollectionMap.ts <- subtool (the map variant) */ const subtools = { getCollection: { orchestrator: 'getCollection', subtools: ['getCollection', 'getCollectionMap'], }, } as const; const templated = ['getCollections', 'getWorkspaces'] as const; export const enabledResources = { full, minimal, code, excludedFromGeneration, subtools, templated, }; - src/tools/utils/toolHelpers.ts:1-13 (helper)Helper utilities imported by getSpecFile: `asMcpError` for converting errors to McpError format, and `ServerContext` type for server context.
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; export { McpError }; export interface ServerContext { serverType: 'full' | 'minimal' | 'code'; availableTools: string[]; } export function asMcpError(error: unknown): McpError { const cause = (error as any)?.cause ?? String(error); return new McpError(ErrorCode.InternalError, cause); } - src/index.ts:263-343 (registration)Dynamic tool registration in index.ts - the server dynamically imports all tool modules (including getSpecFile) from the tools directory and registers them via server.registerTool().
for (const tool of tools) { server.registerTool( tool.method, { description: tool.description, inputSchema: tool.parameters.shape, annotations: tool.annotations || {}, }, async (args, extra) => { const toolName = tool.method; // Keep start event on stderr only to reduce client noise log('info', `Tool invocation started: ${toolName}`, { toolName }); try { const start = Date.now(); const result = await tool.handler(args, { client, headers: { ...extra?.requestInfo?.headers, 'user-agent': clientInfo?.name, }, serverContext, }); const durationMs = Date.now() - start; // Completion: stderr only to avoid spamming client logs log('info', `Tool invocation completed: ${toolName} (${durationMs}ms)`, { toolName, durationMs, }); // Apply template rendering if (result.content?.[0]?.type === 'text') { const rendered = renderTemplate(toolName, result.content[0].text); if (rendered) { return { content: [{ type: 'text' as const, text: rendered }] }; } } return result; } catch (error: any) { const errMsg = String(error?.message || error); // Failures: notify both server stderr and client logBoth(server, 'error', `Tool invocation failed: ${toolName}: ${errMsg}`, { toolName }); if (error instanceof McpError) { const httpStatus = (error.data as Record<string, unknown>)?.httpStatus; if (typeof httpStatus === 'number') { const rawBody = String((error.data as Record<string, unknown>)?.cause ?? ''); let parsedBody: Record<string, unknown> | null = null; try { parsedBody = JSON.parse(rawBody) as Record<string, unknown>; } catch { /* not JSON */ } // Unwrap common { error: { ... } } API response pattern const errorObj = parsedBody?.error && typeof parsedBody.error === 'object' ? (parsedBody.error as Record<string, unknown>) : parsedBody; const rendered = renderErrorTemplate(toolName, httpStatus, { toolName, statusCode: httpStatus, args, errorMessage: error.message, errorBody: rawBody, error: errorObj, }); if (rendered) { throw new McpError(error.code, rendered, error.data); } } throw error; } throw new McpError(ErrorCode.InternalError, `API error: ${error.message}`); } } ); }