Implementing Contract Query and Delay Operations with an MCP Server
This article describes the background, functional requirements, and a complete Node.js implementation for querying contract information and handling contract extensions using natural‑language prompts through an MCP client and server architecture.
Background
With the widespread adoption of MCP, the goal is to enable business users to operate the system through natural‑language descriptions, achieving lower cost, greater convenience, and faster experience.
Implemented Functions
1. Query contract information based on contract status or number:
i. question: "Please help me query contracts pending signature"
ii. Call MCP matching via MCP client
iii. After user confirmation, invoke the contract query MCP server
2. Business contract extension handling:
i. Describe the contract to be extended using natural language
ii. Call MCP client for matching – if the contract is not in the previous list, the large model first verifies its validity
iii. After the query, automatically invoke the contract extension MCP server
iiii. Return result: "Extension successful"
iiiii. Business system verification – success 🏅
Code Implementation
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const QUERY_CONTRACT = "xxxxxxx";
const DELAY_CONTRACT = "xxxxxxx";
// Create server instance
const server = new McpServer({
name: "contract",
version: "1.0.0",
capabilities: {
resources: {},
tools: {},
},
});
// Helper function for making API requests
async function makeRequest(url, params) {
const headers = {
"X-Requested-With": 'XMLHttpRequest',
"content-type": 'application/json',
};
try {
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: JSON.stringify(params),
credentials: 'include',
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return (await response.json());
} catch (error) {
console.error("Error making Contract request:", error);
return null;
}
}
// Format alert data
function formatAlert(feature) {
const props = feature;
return [
`合同号: ${props.contractNumber || "Unknown"}` ,
`合同id: ${props.id || "Unknown"}` ,
`版本号: ${props.version || "Unknown"}` ,
`创建人: ${props.creator || "Unknown"}` ,
`合同名称: ${props.name || "Unknown"}` ,
`合同主体: ${props.ouName || "Unknown"}` ,
`合同类型: ${props.typeName || "Unknown"}` ,
`交易方: ${props.refPartiesName || "Unknown"}` ,
`有效日期至: ${props.endTime || "Unknown"}` ,
"---",
].join("\n");
}
const statusDict = { xx: xx };
// Register tools
server.tool("获取合同列表", "获取某种状态或某个合同的合同列表", {
state: z.string().describe("两或三字的合同状态 (e.g. xx, xx)"),
contractNumber: z.string().describe("合同号 (e.g. xxxxxxx,xxxxxxxx,xxxxxxx)"),
}, async ({ state, contractNumber }) => {
const statusCode = statusDict[state];
const alertsData = await makeRequest(QUERY_CONTRACT, { status: statusCode, pageIndex: 1, pageSize: 10, searchSource: 0, contractNumber });
// ...... 省略业务逻辑 ......
});
server.tool("合同延期", "对指定合同进行延期操作", {
contractId: z.string().describe("合同id (e.g. 41556890,41556953)"),
contractNumber: z.string().describe("合同号 (e.g. PE2025A3709738,BEC2025A3709735)"),
version: z.string().describe("版本号 (e.g. 1,2)"),
endTime: z.string().describe("有效日期至 (e.g. 2023-08-15 12:00:00)"),
}, async ({ contractId, contractNumber, version, endTime }) => {
const alertsData = await makeRequest(DELAY_CONTRACT, { endTime: newEndTime, version, contractNumber, contractId });
// ...... 省略业务逻辑 ......
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Contract MCP Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});Scan the QR code to join the technical discussion group.
JD Tech Talk
Official JD Tech public account delivering best practices and technology innovation.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.