patents-mcp-server 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,9 @@
1
1
  import { UserError } from "fastmcp";
2
2
 
3
3
  //#region src/lib/errors.d.ts
4
+ /** True when the error carries an HTTP 403, however it is shaped. */
5
+ declare const isForbiddenError: (error: unknown) => boolean;
4
6
  declare const handleApiError: (error: unknown) => string;
5
7
  //#endregion
6
- export { UserError, handleApiError };
8
+ export { UserError, handleApiError, isForbiddenError };
7
9
  //# sourceMappingURL=errors.d.ts.map
@@ -1,2 +1,2 @@
1
- import{UserError as e}from"fastmcp";const t={401:`Authentication failed. Please check your API key or credentials.`,403:`Access forbidden. Your credentials do not have permission for this resource.`,404:`Resource not found. The requested patent or endpoint does not exist.`,429:`Rate limit exceeded. Please wait before making additional requests.`},n=e=>t[e.status]||(e.status>=500?`Server error (${e.status}): The patent data service is experiencing issues. Please try again later.`:`HTTP error ${e.status}: ${e.message}`),r=e=>typeof e==`object`&&!!e&&`status`in e&&typeof e.status==`number`,i=e=>typeof e==`object`&&!!e&&`response`in e&&typeof e.response==`object`&&e.response!==null,a=t=>t instanceof e?t.message:i(t)?n({status:t.response.status,message:t.response.statusText}):r(t)?n({status:t.status,message:t.message??`Unknown error`}):t instanceof Error?t.message.includes(`ECONNREFUSED`)?`Connection refused. The patent data service may be unavailable.`:t.message.includes(`ETIMEDOUT`)||t.message.includes(`timeout`)?`Request timed out. The patent data service may be slow or unavailable.`:`Unexpected error: ${t.message}`:`Unknown error occurred: ${String(t)}`;export{e as UserError,a as handleApiError};
1
+ import{UserError as e}from"fastmcp";const t={401:`Authentication failed. Please check your API key or credentials.`,403:`Access forbidden. Your credentials do not have permission for this resource.`,404:`Resource not found. The requested patent or endpoint does not exist.`,429:`Rate limit exceeded. Please wait before making additional requests.`},n=e=>t[e.status]||(e.status>=500?`Server error (${e.status}): The patent data service is experiencing issues. Please try again later.`:`HTTP error ${e.status}: ${e.message}`),r=e=>typeof e==`object`&&!!e&&`status`in e&&typeof e.status==`number`,i=e=>typeof e==`object`&&!!e&&`response`in e&&typeof e.response==`object`&&e.response!==null,a=e=>r(e)?e.status===403:i(e)?e.response.status===403:!1,o=t=>t instanceof e?t.message:i(t)?n({status:t.response.status,message:t.response.statusText}):r(t)?n({status:t.status,message:t.message??`Unknown error`}):t instanceof Error?t.message.includes(`ECONNREFUSED`)?`Connection refused. The patent data service may be unavailable.`:t.message.includes(`ETIMEDOUT`)||t.message.includes(`timeout`)?`Request timed out. The patent data service may be slow or unavailable.`:`Unexpected error: ${t.message}`:`Unknown error occurred: ${String(t)}`;export{e as UserError,o as handleApiError,a as isForbiddenError};
2
2
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../../src/lib/errors.ts"],"sourcesContent":["import { UserError } from \"fastmcp\"\n\nexport { UserError }\n\ntype HttpErrorInfo = {\n status: number\n message: string\n}\n\nconst httpStatusMessages: Record<number, string> = {\n 401: \"Authentication failed. Please check your API key or credentials.\",\n 403: \"Access forbidden. Your credentials do not have permission for this resource.\",\n 404: \"Resource not found. The requested patent or endpoint does not exist.\",\n 429: \"Rate limit exceeded. Please wait before making additional requests.\",\n}\n\nconst formatHttpError = (info: HttpErrorInfo): string => {\n const knownMessage = httpStatusMessages[info.status]\n if (knownMessage) return knownMessage\n\n if (info.status >= 500) {\n return `Server error (${info.status}): The patent data service is experiencing issues. Please try again later.`\n }\n\n return `HTTP error ${info.status}: ${info.message}`\n}\n\nconst isErrorWithStatus = (error: unknown): error is { status: number; message?: string } =>\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof (error as Record<string, unknown>).status === \"number\"\n\nconst isErrorWithResponse = (error: unknown): error is { response: { status: number; statusText: string } } =>\n typeof error === \"object\" &&\n error !== null &&\n \"response\" in error &&\n typeof (error as Record<string, unknown>).response === \"object\" &&\n (error as Record<string, unknown>).response !== null\n\nexport const handleApiError = (error: unknown): string => {\n if (error instanceof UserError) {\n return error.message\n }\n\n if (isErrorWithResponse(error)) {\n return formatHttpError({\n status: error.response.status,\n message: error.response.statusText,\n })\n }\n\n if (isErrorWithStatus(error)) {\n return formatHttpError({\n status: error.status,\n message: (error as { message?: string }).message ?? \"Unknown error\",\n })\n }\n\n if (error instanceof Error) {\n if (error.message.includes(\"ECONNREFUSED\")) {\n return \"Connection refused. The patent data service may be unavailable.\"\n }\n if (error.message.includes(\"ETIMEDOUT\") || error.message.includes(\"timeout\")) {\n return \"Request timed out. The patent data service may be slow or unavailable.\"\n }\n return `Unexpected error: ${error.message}`\n }\n\n return `Unknown error occurred: ${String(error)}`\n}\n"],"mappings":"oCASA,MAAM,EAA6C,CACjD,IAAK,mEACL,IAAK,+EACL,IAAK,uEACL,IAAK,qEACP,EAEM,EAAmB,GACF,EAAmB,EAAK,UAGzC,EAAK,QAAU,IACV,iBAAiB,EAAK,OAAO,4EAG/B,cAAc,EAAK,OAAO,IAAI,EAAK,WAGtC,EAAqB,GACzB,OAAO,GAAU,YACjB,GACA,WAAY,GACZ,OAAQ,EAAkC,QAAW,SAEjD,EAAuB,GAC3B,OAAO,GAAU,YACjB,GACA,aAAc,GACd,OAAQ,EAAkC,UAAa,UACtD,EAAkC,WAAa,KAErC,EAAkB,GACzB,aAAiB,EACZ,EAAM,QAGX,EAAoB,CAAK,EACpB,EAAgB,CACrB,OAAQ,EAAM,SAAS,OACvB,QAAS,EAAM,SAAS,UAC1B,CAAC,EAGC,EAAkB,CAAK,EAClB,EAAgB,CACrB,OAAQ,EAAM,OACd,QAAU,EAA+B,SAAW,eACtD,CAAC,EAGC,aAAiB,MACf,EAAM,QAAQ,SAAS,cAAc,EAChC,kEAEL,EAAM,QAAQ,SAAS,WAAW,GAAK,EAAM,QAAQ,SAAS,SAAS,EAClE,yEAEF,qBAAqB,EAAM,UAG7B,2BAA2B,OAAO,CAAK"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../../src/lib/errors.ts"],"sourcesContent":["import { UserError } from \"fastmcp\"\n\nexport { UserError }\n\ntype HttpErrorInfo = {\n status: number\n message: string\n}\n\nconst httpStatusMessages: Record<number, string> = {\n 401: \"Authentication failed. Please check your API key or credentials.\",\n 403: \"Access forbidden. Your credentials do not have permission for this resource.\",\n 404: \"Resource not found. The requested patent or endpoint does not exist.\",\n 429: \"Rate limit exceeded. Please wait before making additional requests.\",\n}\n\nconst formatHttpError = (info: HttpErrorInfo): string => {\n const knownMessage = httpStatusMessages[info.status]\n if (knownMessage) return knownMessage\n\n if (info.status >= 500) {\n return `Server error (${info.status}): The patent data service is experiencing issues. Please try again later.`\n }\n\n return `HTTP error ${info.status}: ${info.message}`\n}\n\nconst isErrorWithStatus = (error: unknown): error is { status: number; message?: string } =>\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof (error as Record<string, unknown>).status === \"number\"\n\nconst isErrorWithResponse = (error: unknown): error is { response: { status: number; statusText: string } } =>\n typeof error === \"object\" &&\n error !== null &&\n \"response\" in error &&\n typeof (error as Record<string, unknown>).response === \"object\" &&\n (error as Record<string, unknown>).response !== null\n\n/** True when the error carries an HTTP 403, however it is shaped. */\nexport const isForbiddenError = (error: unknown): boolean => {\n if (isErrorWithStatus(error)) return error.status === 403\n if (isErrorWithResponse(error)) return error.response.status === 403\n return false\n}\n\nexport const handleApiError = (error: unknown): string => {\n if (error instanceof UserError) {\n return error.message\n }\n\n if (isErrorWithResponse(error)) {\n return formatHttpError({\n status: error.response.status,\n message: error.response.statusText,\n })\n }\n\n if (isErrorWithStatus(error)) {\n return formatHttpError({\n status: error.status,\n message: (error as { message?: string }).message ?? \"Unknown error\",\n })\n }\n\n if (error instanceof Error) {\n if (error.message.includes(\"ECONNREFUSED\")) {\n return \"Connection refused. The patent data service may be unavailable.\"\n }\n if (error.message.includes(\"ETIMEDOUT\") || error.message.includes(\"timeout\")) {\n return \"Request timed out. The patent data service may be slow or unavailable.\"\n }\n return `Unexpected error: ${error.message}`\n }\n\n return `Unknown error occurred: ${String(error)}`\n}\n"],"mappings":"oCASA,MAAM,EAA6C,CACjD,IAAK,mEACL,IAAK,+EACL,IAAK,uEACL,IAAK,qEACP,EAEM,EAAmB,GACF,EAAmB,EAAK,UAGzC,EAAK,QAAU,IACV,iBAAiB,EAAK,OAAO,4EAG/B,cAAc,EAAK,OAAO,IAAI,EAAK,WAGtC,EAAqB,GACzB,OAAO,GAAU,YACjB,GACA,WAAY,GACZ,OAAQ,EAAkC,QAAW,SAEjD,EAAuB,GAC3B,OAAO,GAAU,YACjB,GACA,aAAc,GACd,OAAQ,EAAkC,UAAa,UACtD,EAAkC,WAAa,KAGrC,EAAoB,GAC3B,EAAkB,CAAK,EAAU,EAAM,SAAW,IAClD,EAAoB,CAAK,EAAU,EAAM,SAAS,SAAW,IAC1D,GAGI,EAAkB,GACzB,aAAiB,EACZ,EAAM,QAGX,EAAoB,CAAK,EACpB,EAAgB,CACrB,OAAQ,EAAM,SAAS,OACvB,QAAS,EAAM,SAAS,UAC1B,CAAC,EAGC,EAAkB,CAAK,EAClB,EAAgB,CACrB,OAAQ,EAAM,OACd,QAAU,EAA+B,SAAW,eACtD,CAAC,EAGC,aAAiB,MACf,EAAM,QAAQ,SAAS,cAAc,EAChC,kEAEL,EAAM,QAAQ,SAAS,WAAW,GAAK,EAAM,QAAQ,SAAS,SAAS,EAClE,yEAEF,qBAAqB,EAAM,UAG7B,2BAA2B,OAAO,CAAK"}
@@ -1,2 +1,2 @@
1
- import{config as e}from"../lib/config.js";import{resourceStore as t}from"../resources/store.js";import{handleApiError as n}from"../lib/errors.js";import{OdpClient as r}from"../clients/odp.client.js";import{z as i}from"zod";const a={readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!0},o=()=>{if(!e.usptoApiKey)throw Error(`USPTO_API_KEY is required for ODP tools`);return new r({apiKey:e.usptoApiKey,timeout:e.requestTimeout})},s=async(n,r,i,a=t,o=e.publicBaseUrl)=>{let{data:s}=await n.downloadDocument(r,i),{id:c}=a.put(Buffer.from(s),`pdf`);return JSON.stringify({url:`${o}/resources/${c}.pdf`,mimeType:`application/pdf`,expiresInSeconds:a.ttlSeconds})},c=e=>{e.addTool({name:`odp-search-applications`,description:`Search USPTO patent applications via the Open Data Portal. Coverage: applications filed January 1, 2001 and later. Supports full-text search across application data.`,parameters:i.object({query:i.string().describe(`Search query text`),limit:i.number().int().min(1).max(100).default(25).describe(`Number of results to return (1-100)`),offset:i.number().int().min(0).default(0).describe(`Result offset for pagination`),sort:i.string().optional().describe(`Sort field and direction`)}),annotations:a,execute:async e=>{try{let t=await o().searchApplications(e.query,e.limit,e.offset,e.sort);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-application`,description:`Get detailed information about a specific USPTO patent application by application number. Returns filing data, status, claims, and other application details.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getApplication(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-application-metadata`,description:`Get metadata for a USPTO patent application including application type, entity status, and dates.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getApplicationMetadata(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-continuity`,description:`Get continuity data (parent/child relationships) for a patent application. Shows continuation, divisional, and CIP relationships.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getContinuity(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-assignment`,description:`Get assignment/ownership records for a patent application. Shows current and historical assignees.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getAssignment(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-adjustment`,description:`Get patent term adjustment (PTA) data for an application. Shows delays attributable to the USPTO and applicant.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getAdjustment(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-attorney`,description:`Get attorney/agent information for a patent application.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getAttorney(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-foreign-priority`,description:`Get foreign priority claims for a patent application.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getForeignPriority(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-transactions`,description:`Get transaction history for a patent application. Shows all prosecution events in chronological order.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getTransactions(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-documents`,description:`Get document listing for a patent application. Returns metadata about filed and issued documents.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getDocuments(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-download-document`,description:`Download a patent file-wrapper document as a PDF from the USPTO Open Data Portal. Provide an application number and the documentIdentifier from odp-get-documents (downloadOptionBag). The server's USPTO_API_KEY authenticates the fetch and follows the ODP redirect, then caches the PDF transiently and returns a fetchable URL JSON of the form { url, mimeType, expiresInSeconds }. Fetch the URL to retrieve the PDF; it expires after expiresInSeconds.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`),documentIdentifier:i.string().describe(`Document identifier from odp-get-documents downloadOptionBag (e.g., 'M4IR8IRKWFYGX56')`)}),annotations:a,execute:async e=>{try{return await s(o(),e.applicationNumberText,e.documentIdentifier)}catch(e){return n(e)}}}),e.addTool({name:`odp-search-datasets`,description:`Search USPTO bulk data datasets available through the Open Data Portal.`,parameters:i.object({query:i.string().describe(`Search query for datasets`)}),annotations:a,execute:async e=>{try{let t=await o().searchDatasets(e.query);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-dataset`,description:`Get details about a specific USPTO bulk data dataset by product ID.`,parameters:i.object({productId:i.string().describe(`Dataset product identifier`)}),annotations:a,execute:async e=>{try{let t=await o().getDataset(e.productId);return JSON.stringify(t)}catch(e){return n(e)}}})};export{s as buildDownloadResult,c as registerOdpTools};
1
+ import{config as e}from"../lib/config.js";import{resourceStore as t}from"../resources/store.js";import{handleApiError as n}from"../lib/errors.js";import{OdpClient as r}from"../clients/odp.client.js";import{z as i}from"zod";const a={readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!0},o=()=>{if(!e.usptoApiKey)throw Error(`USPTO_API_KEY is required for ODP tools`);return new r({apiKey:e.usptoApiKey,timeout:e.requestTimeout})},s=async(n,r,i,a=t,o=e.publicBaseUrl)=>{let{data:s}=await n.downloadDocument(r,i),{id:c}=a.put(Buffer.from(s),`pdf`);return JSON.stringify({url:`${o}/resources/${c}.pdf`,mimeType:`application/pdf`,expiresInSeconds:a.ttlSeconds})},c=e=>{e.addTool({name:`odp-search-applications`,description:`Search USPTO patent applications via the Open Data Portal. Coverage: applications filed January 1, 2001 and later. Supports full-text search across application data.`,parameters:i.object({query:i.string().describe(`Search query text`),limit:i.number().int().min(1).max(100).default(25).describe(`Number of results to return (1-100)`),offset:i.number().int().min(0).default(0).describe(`Result offset for pagination`),sort:i.string().optional().describe(`Sort field and direction`)}),annotations:a,execute:async e=>{try{let t=await o().searchApplications(e.query,e.limit,e.offset,e.sort);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-application`,description:`Get detailed information about a specific USPTO patent application by application number. Returns filing data, status, claims, and other application details.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getApplication(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-application-metadata`,description:`Get metadata for a USPTO patent application including application type, entity status, and dates.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getApplicationMetadata(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-continuity`,description:`Get continuity data (parent/child relationships) for a patent application. Shows continuation, divisional, and CIP relationships.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getContinuity(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-assignment`,description:`Get assignment/ownership records for a patent application. Shows current and historical assignees.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getAssignment(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-adjustment`,description:`Get patent term adjustment (PTA) data for an application. Shows delays attributable to the USPTO and applicant.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getAdjustment(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-attorney`,description:`Get attorney/agent information for a patent application.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getAttorney(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-foreign-priority`,description:`Get foreign priority claims for a patent application.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getForeignPriority(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-transactions`,description:`Get transaction history for a patent application. Shows all prosecution events in chronological order.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getTransactions(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-documents`,description:`Get document listing for a patent application. Returns metadata about filed and issued documents.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await o().getDocuments(e.applicationNumberText);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-download-document`,description:`Retrieve the full text and content of any patent file-wrapper document specifications, claims, drawings, office actions (rejections), applicant amendments and remarks, interview summaries, examiner search notes, and prior-art reference lists. This is the authoritative way to read what a document actually says: fetch the documentIdentifier from odp-get-documents (downloadOptionBag), and this tool downloads it and returns a fetchable URL (JSON of the form { url, mimeType, expiresInSeconds }; fetch the URL to retrieve the PDF, which expires after expiresInSeconds). Use this whenever a question requires the contents of a prosecution document — e.g. "what was the examiner's rejection," "how did the applicant respond," "what prior art was cited." It is also the reliable fallback when the structured office-action endpoints (office-action-get-text/-rejections/-citations) are unavailable or return access errors, since those depend on a separate USPTO data tier. Note: older documents are often scanned images with no embedded text layer. The returned PDF is still complete and readable — the consumer should OCR it (rasterize + text-recognize) when direct text extraction yields nothing.`,parameters:i.object({applicationNumberText:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`),documentIdentifier:i.string().describe(`Document identifier from odp-get-documents downloadOptionBag (e.g., 'M4IR8IRKWFYGX56')`)}),annotations:a,execute:async e=>{try{return await s(o(),e.applicationNumberText,e.documentIdentifier)}catch(e){return n(e)}}}),e.addTool({name:`odp-search-datasets`,description:`Search USPTO bulk data datasets available through the Open Data Portal.`,parameters:i.object({query:i.string().describe(`Search query for datasets`)}),annotations:a,execute:async e=>{try{let t=await o().searchDatasets(e.query);return JSON.stringify(t)}catch(e){return n(e)}}}),e.addTool({name:`odp-get-dataset`,description:`Get details about a specific USPTO bulk data dataset by product ID.`,parameters:i.object({productId:i.string().describe(`Dataset product identifier`)}),annotations:a,execute:async e=>{try{let t=await o().getDataset(e.productId);return JSON.stringify(t)}catch(e){return n(e)}}})};export{s as buildDownloadResult,c as registerOdpTools};
2
2
  //# sourceMappingURL=odp.tools.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"odp.tools.js","names":[],"sources":["../../src/tools/odp.tools.ts"],"sourcesContent":["import type { FastMCP } from \"fastmcp\"\nimport { z } from \"zod\"\n\nimport { OdpClient } from \"../clients/odp.client\"\nimport { config } from \"../lib/config\"\nimport { handleApiError } from \"../lib/errors\"\nimport { type FileStore, resourceStore } from \"../resources/store\"\n\nconst ODP_ANNOTATIONS = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n} as const\n\nconst createClient = (): OdpClient => {\n if (!config.usptoApiKey) {\n throw new Error(\"USPTO_API_KEY is required for ODP tools\")\n }\n return new OdpClient({\n apiKey: config.usptoApiKey,\n timeout: config.requestTimeout,\n })\n}\n\n/**\n * Fetches a file-wrapper PDF from USPTO, stashes it in the transient store, and returns the\n * JSON payload the tool surfaces: a fetchable URL on the server's own host (never the bytes,\n * never the USPTO key). Exported for testing.\n */\nexport const buildDownloadResult = async (\n client: Pick<OdpClient, \"downloadDocument\">,\n applicationNumberText: string,\n documentIdentifier: string,\n store: FileStore = resourceStore,\n baseUrl: string = config.publicBaseUrl,\n): Promise<string> => {\n const { data } = await client.downloadDocument(applicationNumberText, documentIdentifier)\n const { id } = store.put(Buffer.from(data), \"pdf\")\n return JSON.stringify({\n url: `${baseUrl}/resources/${id}.pdf`,\n mimeType: \"application/pdf\",\n expiresInSeconds: store.ttlSeconds,\n })\n}\n\nexport const registerOdpTools = (server: FastMCP): void => {\n server.addTool({\n name: \"odp-search-applications\",\n description:\n \"Search USPTO patent applications via the Open Data Portal. Coverage: applications filed January 1, 2001 and later. Supports full-text search across application data.\",\n parameters: z.object({\n query: z.string().describe(\"Search query text\"),\n limit: z.number().int().min(1).max(100).default(25).describe(\"Number of results to return (1-100)\"),\n offset: z.number().int().min(0).default(0).describe(\"Result offset for pagination\"),\n sort: z.string().optional().describe(\"Sort field and direction\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.searchApplications(args.query, args.limit, args.offset, args.sort)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-application\",\n description:\n \"Get detailed information about a specific USPTO patent application by application number. Returns filing data, status, claims, and other application details.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getApplication(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-application-metadata\",\n description: \"Get metadata for a USPTO patent application including application type, entity status, and dates.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getApplicationMetadata(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-continuity\",\n description:\n \"Get continuity data (parent/child relationships) for a patent application. Shows continuation, divisional, and CIP relationships.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getContinuity(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-assignment\",\n description: \"Get assignment/ownership records for a patent application. Shows current and historical assignees.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getAssignment(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-adjustment\",\n description:\n \"Get patent term adjustment (PTA) data for an application. Shows delays attributable to the USPTO and applicant.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getAdjustment(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-attorney\",\n description: \"Get attorney/agent information for a patent application.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getAttorney(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-foreign-priority\",\n description: \"Get foreign priority claims for a patent application.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getForeignPriority(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-transactions\",\n description:\n \"Get transaction history for a patent application. Shows all prosecution events in chronological order.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getTransactions(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-documents\",\n description: \"Get document listing for a patent application. Returns metadata about filed and issued documents.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getDocuments(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-download-document\",\n description:\n \"Download a patent file-wrapper document as a PDF from the USPTO Open Data Portal. Provide an application number and the documentIdentifier from odp-get-documents (downloadOptionBag). The server's USPTO_API_KEY authenticates the fetch and follows the ODP redirect, then caches the PDF transiently and returns a fetchable URL — JSON of the form { url, mimeType, expiresInSeconds }. Fetch the URL to retrieve the PDF; it expires after expiresInSeconds.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n documentIdentifier: z\n .string()\n .describe(\"Document identifier from odp-get-documents downloadOptionBag (e.g., 'M4IR8IRKWFYGX56')\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n return await buildDownloadResult(client, args.applicationNumberText, args.documentIdentifier)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-search-datasets\",\n description: \"Search USPTO bulk data datasets available through the Open Data Portal.\",\n parameters: z.object({\n query: z.string().describe(\"Search query for datasets\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.searchDatasets(args.query)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-dataset\",\n description: \"Get details about a specific USPTO bulk data dataset by product ID.\",\n parameters: z.object({\n productId: z.string().describe(\"Dataset product identifier\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getDataset(args.productId)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"odp.tools.js","names":[],"sources":["../../src/tools/odp.tools.ts"],"sourcesContent":["import type { FastMCP } from \"fastmcp\"\nimport { z } from \"zod\"\n\nimport { OdpClient } from \"../clients/odp.client\"\nimport { config } from \"../lib/config\"\nimport { handleApiError } from \"../lib/errors\"\nimport { type FileStore, resourceStore } from \"../resources/store\"\n\nconst ODP_ANNOTATIONS = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n} as const\n\nconst createClient = (): OdpClient => {\n if (!config.usptoApiKey) {\n throw new Error(\"USPTO_API_KEY is required for ODP tools\")\n }\n return new OdpClient({\n apiKey: config.usptoApiKey,\n timeout: config.requestTimeout,\n })\n}\n\n/**\n * Fetches a file-wrapper PDF from USPTO, stashes it in the transient store, and returns the\n * JSON payload the tool surfaces: a fetchable URL on the server's own host (never the bytes,\n * never the USPTO key). Exported for testing.\n */\nexport const buildDownloadResult = async (\n client: Pick<OdpClient, \"downloadDocument\">,\n applicationNumberText: string,\n documentIdentifier: string,\n store: FileStore = resourceStore,\n baseUrl: string = config.publicBaseUrl,\n): Promise<string> => {\n const { data } = await client.downloadDocument(applicationNumberText, documentIdentifier)\n const { id } = store.put(Buffer.from(data), \"pdf\")\n return JSON.stringify({\n url: `${baseUrl}/resources/${id}.pdf`,\n mimeType: \"application/pdf\",\n expiresInSeconds: store.ttlSeconds,\n })\n}\n\nexport const registerOdpTools = (server: FastMCP): void => {\n server.addTool({\n name: \"odp-search-applications\",\n description:\n \"Search USPTO patent applications via the Open Data Portal. Coverage: applications filed January 1, 2001 and later. Supports full-text search across application data.\",\n parameters: z.object({\n query: z.string().describe(\"Search query text\"),\n limit: z.number().int().min(1).max(100).default(25).describe(\"Number of results to return (1-100)\"),\n offset: z.number().int().min(0).default(0).describe(\"Result offset for pagination\"),\n sort: z.string().optional().describe(\"Sort field and direction\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.searchApplications(args.query, args.limit, args.offset, args.sort)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-application\",\n description:\n \"Get detailed information about a specific USPTO patent application by application number. Returns filing data, status, claims, and other application details.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getApplication(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-application-metadata\",\n description: \"Get metadata for a USPTO patent application including application type, entity status, and dates.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getApplicationMetadata(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-continuity\",\n description:\n \"Get continuity data (parent/child relationships) for a patent application. Shows continuation, divisional, and CIP relationships.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getContinuity(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-assignment\",\n description: \"Get assignment/ownership records for a patent application. Shows current and historical assignees.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getAssignment(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-adjustment\",\n description:\n \"Get patent term adjustment (PTA) data for an application. Shows delays attributable to the USPTO and applicant.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getAdjustment(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-attorney\",\n description: \"Get attorney/agent information for a patent application.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getAttorney(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-foreign-priority\",\n description: \"Get foreign priority claims for a patent application.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getForeignPriority(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-transactions\",\n description:\n \"Get transaction history for a patent application. Shows all prosecution events in chronological order.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getTransactions(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-documents\",\n description: \"Get document listing for a patent application. Returns metadata about filed and issued documents.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getDocuments(args.applicationNumberText)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-download-document\",\n description:\n \"Retrieve the full text and content of any patent file-wrapper document — specifications, claims, drawings, office actions (rejections), applicant amendments and remarks, interview summaries, examiner search notes, and prior-art reference lists. This is the authoritative way to read what a document actually says: fetch the documentIdentifier from odp-get-documents (downloadOptionBag), and this tool downloads it and returns a fetchable URL (JSON of the form { url, mimeType, expiresInSeconds }; fetch the URL to retrieve the PDF, which expires after expiresInSeconds). \" +\n 'Use this whenever a question requires the contents of a prosecution document — e.g. \"what was the examiner\\'s rejection,\" \"how did the applicant respond,\" \"what prior art was cited.\" It is also the reliable fallback when the structured office-action endpoints (office-action-get-text/-rejections/-citations) are unavailable or return access errors, since those depend on a separate USPTO data tier. ' +\n \"Note: older documents are often scanned images with no embedded text layer. The returned PDF is still complete and readable — the consumer should OCR it (rasterize + text-recognize) when direct text extraction yields nothing.\",\n parameters: z.object({\n applicationNumberText: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n documentIdentifier: z\n .string()\n .describe(\"Document identifier from odp-get-documents downloadOptionBag (e.g., 'M4IR8IRKWFYGX56')\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n return await buildDownloadResult(client, args.applicationNumberText, args.documentIdentifier)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-search-datasets\",\n description: \"Search USPTO bulk data datasets available through the Open Data Portal.\",\n parameters: z.object({\n query: z.string().describe(\"Search query for datasets\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.searchDatasets(args.query)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"odp-get-dataset\",\n description: \"Get details about a specific USPTO bulk data dataset by product ID.\",\n parameters: z.object({\n productId: z.string().describe(\"Dataset product identifier\"),\n }),\n annotations: ODP_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getDataset(args.productId)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n}\n"],"mappings":"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"}
@@ -1,7 +1,14 @@
1
1
  import { FastMCP } from "fastmcp";
2
2
 
3
3
  //#region src/tools/office-actions.tools.d.ts
4
+ /**
5
+ * The structured office-action endpoints sit on a USPTO data tier the ODP key is not entitled to,
6
+ * so they return HTTP 403 even when ODP itself is healthy. Rather than dead-ending, route the agent
7
+ * to the file-wrapper download path, which serves the same content (the actual office-action PDFs).
8
+ */
9
+ declare const OA_FALLBACK_MESSAGE: string;
10
+ declare const handleOfficeActionError: (error: unknown) => string;
4
11
  declare const registerOfficeActionsTools: (server: FastMCP) => void;
5
12
  //#endregion
6
- export { registerOfficeActionsTools };
13
+ export { OA_FALLBACK_MESSAGE, handleOfficeActionError, registerOfficeActionsTools };
7
14
  //# sourceMappingURL=office-actions.tools.d.ts.map
@@ -1,2 +1,2 @@
1
- import{config as e}from"../lib/config.js";import{handleApiError as t}from"../lib/errors.js";import{OdpClient as n}from"../clients/odp.client.js";import{z as r}from"zod";const i={readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!0},a=()=>new n({apiKey:e.usptoApiKey??(()=>{throw Error(`USPTO_API_KEY is required`)})(),timeout:e.requestTimeout}),o=e=>{e.addTool({name:`office-action-get-text`,description:`Get the full text of office actions for a patent application. Includes examiner rejections, objections, and requirements.`,parameters:r.object({applicationNumber:r.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:i,execute:async e=>{try{let t=await a().getOfficeActionText(e.applicationNumber);return JSON.stringify(t)}catch(e){return t(e)}}}),e.addTool({name:`office-action-search`,description:`Search office actions across USPTO patent applications.`,parameters:r.object({query:r.string().describe(`Search query text`),limit:r.number().int().min(1).max(100).default(25).describe(`Number of results to return (1-100)`)}),annotations:i,execute:async e=>{try{let t=await a().searchOfficeActions(e.query,e.limit);return JSON.stringify(t)}catch(e){return t(e)}}}),e.addTool({name:`office-action-get-citations`,description:`Get prior art citations from office actions for a patent application. Shows references cited by the examiner.`,parameters:r.object({applicationNumber:r.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:i,execute:async e=>{try{let t=await a().getOfficeActionCitations(e.applicationNumber);return JSON.stringify(t)}catch(e){return t(e)}}}),e.addTool({name:`office-action-get-rejections`,description:`Get rejection data from office actions for a patent application. Includes rejection types (35 USC 101, 102, 103, 112) and affected claims.`,parameters:r.object({applicationNumber:r.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:i,execute:async e=>{try{let t=await a().getOfficeActionRejections(e.applicationNumber);return JSON.stringify(t)}catch(e){return t(e)}}})};export{o as registerOfficeActionsTools};
1
+ import{config as e}from"../lib/config.js";import{handleApiError as t,isForbiddenError as n}from"../lib/errors.js";import{OdpClient as r}from"../clients/odp.client.js";import{z as i}from"zod";const a={readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!0},o=`The structured office-action endpoint is unavailable for this credential (HTTP 403 — the office-action data tier is not part of the USPTO ODP product this key is entitled to). To read office-action content, list the application's documents with odp-get-documents, then download the relevant office-action document with odp-download-document and read the returned PDF (OCR it if it is a scanned image with no text layer).`,s=e=>n(e)?o:t(e),c=()=>new r({apiKey:e.usptoApiKey??(()=>{throw Error(`USPTO_API_KEY is required`)})(),timeout:e.requestTimeout}),l=e=>{e.addTool({name:`office-action-get-text`,description:`Get the full text of office actions for a patent application. Includes examiner rejections, objections, and requirements.`,parameters:i.object({applicationNumber:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await c().getOfficeActionText(e.applicationNumber);return JSON.stringify(t)}catch(e){return s(e)}}}),e.addTool({name:`office-action-search`,description:`Search office actions across USPTO patent applications.`,parameters:i.object({query:i.string().describe(`Search query text`),limit:i.number().int().min(1).max(100).default(25).describe(`Number of results to return (1-100)`)}),annotations:a,execute:async e=>{try{let t=await c().searchOfficeActions(e.query,e.limit);return JSON.stringify(t)}catch(e){return s(e)}}}),e.addTool({name:`office-action-get-citations`,description:`Get prior art citations from office actions for a patent application. Shows references cited by the examiner.`,parameters:i.object({applicationNumber:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await c().getOfficeActionCitations(e.applicationNumber);return JSON.stringify(t)}catch(e){return s(e)}}}),e.addTool({name:`office-action-get-rejections`,description:`Get rejection data from office actions for a patent application. Includes rejection types (35 USC 101, 102, 103, 112) and affected claims.`,parameters:i.object({applicationNumber:i.string().describe(`Application number (e.g., 16/123,456 or 16123456)`)}),annotations:a,execute:async e=>{try{let t=await c().getOfficeActionRejections(e.applicationNumber);return JSON.stringify(t)}catch(e){return s(e)}}})};export{o as OA_FALLBACK_MESSAGE,s as handleOfficeActionError,l as registerOfficeActionsTools};
2
2
  //# sourceMappingURL=office-actions.tools.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"office-actions.tools.js","names":[],"sources":["../../src/tools/office-actions.tools.ts"],"sourcesContent":["import type { FastMCP } from \"fastmcp\"\nimport { z } from \"zod\"\n\nimport { OdpClient } from \"../clients/odp.client\"\nimport { config } from \"../lib/config\"\nimport { handleApiError } from \"../lib/errors\"\n\nconst OA_ANNOTATIONS = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n} as const\n\nconst createClient = (): OdpClient => {\n return new OdpClient({\n apiKey:\n config.usptoApiKey ??\n (() => {\n throw new Error(\"USPTO_API_KEY is required\")\n })(),\n timeout: config.requestTimeout,\n })\n}\n\nexport const registerOfficeActionsTools = (server: FastMCP): void => {\n server.addTool({\n name: \"office-action-get-text\",\n description:\n \"Get the full text of office actions for a patent application. Includes examiner rejections, objections, and requirements.\",\n parameters: z.object({\n applicationNumber: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: OA_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getOfficeActionText(args.applicationNumber)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"office-action-search\",\n description: \"Search office actions across USPTO patent applications.\",\n parameters: z.object({\n query: z.string().describe(\"Search query text\"),\n limit: z.number().int().min(1).max(100).default(25).describe(\"Number of results to return (1-100)\"),\n }),\n annotations: OA_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.searchOfficeActions(args.query, args.limit)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"office-action-get-citations\",\n description:\n \"Get prior art citations from office actions for a patent application. Shows references cited by the examiner.\",\n parameters: z.object({\n applicationNumber: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: OA_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getOfficeActionCitations(args.applicationNumber)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n\n server.addTool({\n name: \"office-action-get-rejections\",\n description:\n \"Get rejection data from office actions for a patent application. Includes rejection types (35 USC 101, 102, 103, 112) and affected claims.\",\n parameters: z.object({\n applicationNumber: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: OA_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getOfficeActionRejections(args.applicationNumber)\n return JSON.stringify(result)\n } catch (error) {\n return handleApiError(error)\n }\n },\n })\n}\n"],"mappings":"yKAOA,MAAM,EAAiB,CACrB,aAAc,GACd,gBAAiB,GACjB,eAAgB,GAChB,cAAe,EACjB,EAEM,MACG,IAAI,EAAU,CACnB,OACE,EAAO,kBACA,CACL,MAAU,MAAM,2BAA2B,CAC7C,GAAG,EACL,QAAS,EAAO,cAClB,CAAC,EAGU,EAA8B,GAA0B,CACnE,EAAO,QAAQ,CACb,KAAM,yBACN,YACE,4HACF,WAAY,EAAE,OAAO,CACnB,kBAAmB,EAAE,OAAO,EAAE,SAAS,mDAAmD,CAC5F,CAAC,EACD,YAAa,EACb,QAAS,KAAO,IAAS,CACvB,GAAI,CAEF,IAAM,EAAS,MADA,EACW,EAAE,oBAAoB,EAAK,iBAAiB,EACtE,OAAO,KAAK,UAAU,CAAM,CAC9B,OAAS,EAAO,CACd,OAAO,EAAe,CAAK,CAC7B,CACF,CACF,CAAC,EAED,EAAO,QAAQ,CACb,KAAM,uBACN,YAAa,0DACb,WAAY,EAAE,OAAO,CACnB,MAAO,EAAE,OAAO,EAAE,SAAS,mBAAmB,EAC9C,MAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,qCAAqC,CACpG,CAAC,EACD,YAAa,EACb,QAAS,KAAO,IAAS,CACvB,GAAI,CAEF,IAAM,EAAS,MADA,EACW,EAAE,oBAAoB,EAAK,MAAO,EAAK,KAAK,EACtE,OAAO,KAAK,UAAU,CAAM,CAC9B,OAAS,EAAO,CACd,OAAO,EAAe,CAAK,CAC7B,CACF,CACF,CAAC,EAED,EAAO,QAAQ,CACb,KAAM,8BACN,YACE,gHACF,WAAY,EAAE,OAAO,CACnB,kBAAmB,EAAE,OAAO,EAAE,SAAS,mDAAmD,CAC5F,CAAC,EACD,YAAa,EACb,QAAS,KAAO,IAAS,CACvB,GAAI,CAEF,IAAM,EAAS,MADA,EACW,EAAE,yBAAyB,EAAK,iBAAiB,EAC3E,OAAO,KAAK,UAAU,CAAM,CAC9B,OAAS,EAAO,CACd,OAAO,EAAe,CAAK,CAC7B,CACF,CACF,CAAC,EAED,EAAO,QAAQ,CACb,KAAM,+BACN,YACE,6IACF,WAAY,EAAE,OAAO,CACnB,kBAAmB,EAAE,OAAO,EAAE,SAAS,mDAAmD,CAC5F,CAAC,EACD,YAAa,EACb,QAAS,KAAO,IAAS,CACvB,GAAI,CAEF,IAAM,EAAS,MADA,EACW,EAAE,0BAA0B,EAAK,iBAAiB,EAC5E,OAAO,KAAK,UAAU,CAAM,CAC9B,OAAS,EAAO,CACd,OAAO,EAAe,CAAK,CAC7B,CACF,CACF,CAAC,CACH"}
1
+ {"version":3,"file":"office-actions.tools.js","names":[],"sources":["../../src/tools/office-actions.tools.ts"],"sourcesContent":["import type { FastMCP } from \"fastmcp\"\nimport { z } from \"zod\"\n\nimport { OdpClient } from \"../clients/odp.client\"\nimport { config } from \"../lib/config\"\nimport { handleApiError, isForbiddenError } from \"../lib/errors\"\n\nconst OA_ANNOTATIONS = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n} as const\n\n/**\n * The structured office-action endpoints sit on a USPTO data tier the ODP key is not entitled to,\n * so they return HTTP 403 even when ODP itself is healthy. Rather than dead-ending, route the agent\n * to the file-wrapper download path, which serves the same content (the actual office-action PDFs).\n */\nexport const OA_FALLBACK_MESSAGE =\n \"The structured office-action endpoint is unavailable for this credential (HTTP 403 — the office-action \" +\n \"data tier is not part of the USPTO ODP product this key is entitled to). To read office-action content, \" +\n \"list the application's documents with odp-get-documents, then download the relevant office-action document \" +\n \"with odp-download-document and read the returned PDF (OCR it if it is a scanned image with no text layer).\"\n\nexport const handleOfficeActionError = (error: unknown): string =>\n isForbiddenError(error) ? OA_FALLBACK_MESSAGE : handleApiError(error)\n\nconst createClient = (): OdpClient => {\n return new OdpClient({\n apiKey:\n config.usptoApiKey ??\n (() => {\n throw new Error(\"USPTO_API_KEY is required\")\n })(),\n timeout: config.requestTimeout,\n })\n}\n\nexport const registerOfficeActionsTools = (server: FastMCP): void => {\n server.addTool({\n name: \"office-action-get-text\",\n description:\n \"Get the full text of office actions for a patent application. Includes examiner rejections, objections, and requirements.\",\n parameters: z.object({\n applicationNumber: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: OA_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getOfficeActionText(args.applicationNumber)\n return JSON.stringify(result)\n } catch (error) {\n return handleOfficeActionError(error)\n }\n },\n })\n\n server.addTool({\n name: \"office-action-search\",\n description: \"Search office actions across USPTO patent applications.\",\n parameters: z.object({\n query: z.string().describe(\"Search query text\"),\n limit: z.number().int().min(1).max(100).default(25).describe(\"Number of results to return (1-100)\"),\n }),\n annotations: OA_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.searchOfficeActions(args.query, args.limit)\n return JSON.stringify(result)\n } catch (error) {\n return handleOfficeActionError(error)\n }\n },\n })\n\n server.addTool({\n name: \"office-action-get-citations\",\n description:\n \"Get prior art citations from office actions for a patent application. Shows references cited by the examiner.\",\n parameters: z.object({\n applicationNumber: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: OA_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getOfficeActionCitations(args.applicationNumber)\n return JSON.stringify(result)\n } catch (error) {\n return handleOfficeActionError(error)\n }\n },\n })\n\n server.addTool({\n name: \"office-action-get-rejections\",\n description:\n \"Get rejection data from office actions for a patent application. Includes rejection types (35 USC 101, 102, 103, 112) and affected claims.\",\n parameters: z.object({\n applicationNumber: z.string().describe(\"Application number (e.g., 16/123,456 or 16123456)\"),\n }),\n annotations: OA_ANNOTATIONS,\n execute: async (args) => {\n try {\n const client = createClient()\n const result = await client.getOfficeActionRejections(args.applicationNumber)\n return JSON.stringify(result)\n } catch (error) {\n return handleOfficeActionError(error)\n }\n },\n })\n}\n"],"mappings":"+LAOA,MAAM,EAAiB,CACrB,aAAc,GACd,gBAAiB,GACjB,eAAgB,GAChB,cAAe,EACjB,EAOa,EACX,uaAKW,EAA2B,GACtC,EAAiB,CAAK,EAAI,EAAsB,EAAe,CAAK,EAEhE,MACG,IAAI,EAAU,CACnB,OACE,EAAO,kBACA,CACL,MAAU,MAAM,2BAA2B,CAC7C,GAAG,EACL,QAAS,EAAO,cAClB,CAAC,EAGU,EAA8B,GAA0B,CACnE,EAAO,QAAQ,CACb,KAAM,yBACN,YACE,4HACF,WAAY,EAAE,OAAO,CACnB,kBAAmB,EAAE,OAAO,EAAE,SAAS,mDAAmD,CAC5F,CAAC,EACD,YAAa,EACb,QAAS,KAAO,IAAS,CACvB,GAAI,CAEF,IAAM,EAAS,MADA,EACW,EAAE,oBAAoB,EAAK,iBAAiB,EACtE,OAAO,KAAK,UAAU,CAAM,CAC9B,OAAS,EAAO,CACd,OAAO,EAAwB,CAAK,CACtC,CACF,CACF,CAAC,EAED,EAAO,QAAQ,CACb,KAAM,uBACN,YAAa,0DACb,WAAY,EAAE,OAAO,CACnB,MAAO,EAAE,OAAO,EAAE,SAAS,mBAAmB,EAC9C,MAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,qCAAqC,CACpG,CAAC,EACD,YAAa,EACb,QAAS,KAAO,IAAS,CACvB,GAAI,CAEF,IAAM,EAAS,MADA,EACW,EAAE,oBAAoB,EAAK,MAAO,EAAK,KAAK,EACtE,OAAO,KAAK,UAAU,CAAM,CAC9B,OAAS,EAAO,CACd,OAAO,EAAwB,CAAK,CACtC,CACF,CACF,CAAC,EAED,EAAO,QAAQ,CACb,KAAM,8BACN,YACE,gHACF,WAAY,EAAE,OAAO,CACnB,kBAAmB,EAAE,OAAO,EAAE,SAAS,mDAAmD,CAC5F,CAAC,EACD,YAAa,EACb,QAAS,KAAO,IAAS,CACvB,GAAI,CAEF,IAAM,EAAS,MADA,EACW,EAAE,yBAAyB,EAAK,iBAAiB,EAC3E,OAAO,KAAK,UAAU,CAAM,CAC9B,OAAS,EAAO,CACd,OAAO,EAAwB,CAAK,CACtC,CACF,CACF,CAAC,EAED,EAAO,QAAQ,CACb,KAAM,+BACN,YACE,6IACF,WAAY,EAAE,OAAO,CACnB,kBAAmB,EAAE,OAAO,EAAE,SAAS,mDAAmD,CAC5F,CAAC,EACD,YAAa,EACb,QAAS,KAAO,IAAS,CACvB,GAAI,CAEF,IAAM,EAAS,MADA,EACW,EAAE,0BAA0B,EAAK,iBAAiB,EAC5E,OAAO,KAAK,UAAU,CAAM,CAC9B,OAAS,EAAO,CACd,OAAO,EAAwB,CAAK,CACtC,CACF,CACF,CAAC,CACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patents-mcp-server",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "FastMCP TypeScript patent intelligence MCP server — 55 tools across USPTO, EPO, and BigQuery",
5
5
  "keywords": [
6
6
  "mcp",