accurlex-mcp-server 0.4.1 → 0.4.2

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +17 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "accurlex-mcp-server",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "description": "MCP server for accurLex Chinese legal AI — legal Q&A, contract review, law lookup, document drafting",
6
6
  "keywords": ["mcp", "legal", "chinese-law", "contract-review", "accurlex", "ai"],
package/src/index.js CHANGED
@@ -24,11 +24,12 @@ const BEARER_TOKEN = (process.env.ACCURLEX_BEARER_TOKEN || '').trim();
24
24
 
25
25
  const TEXT_FILE_EXTENSIONS = new Set(['.txt', '.text', '.md', '.json', '.csv']);
26
26
  const MAX_INPUT_CHARS = 10000;
27
+ const MAX_INPUT_CHARS_PAID = 30000;
27
28
 
28
29
  const server = new Server(
29
30
  {
30
31
  name: 'accurlex-mcp-server',
31
- version: '0.4.1',
32
+ version: '0.4.2',
32
33
  },
33
34
  {
34
35
  capabilities: {
@@ -44,7 +45,7 @@ const tools = [
44
45
  inputSchema: {
45
46
  type: 'object',
46
47
  properties: {
47
- question: { type: 'string', maxLength: 10000, description: 'The legal question to analyze (max 10000 chars).' },
48
+ question: { type: 'string', maxLength: 30000, description: 'The legal question to analyze (free/deep: max 10000 chars, expert: max 30000 chars).' },
48
49
  mode: {
49
50
  type: 'string',
50
51
  enum: ['deep', 'expert'],
@@ -62,7 +63,7 @@ const tools = [
62
63
  required: ['role', 'content'],
63
64
  },
64
65
  },
65
- context_text: { type: 'string', maxLength: 10000, description: 'Optional background facts or extracted file text.' },
66
+ context_text: { type: 'string', maxLength: 30000, description: 'Optional background facts or extracted file text (free/deep: max 10000 chars, expert: max 30000 chars).' },
66
67
  },
67
68
  required: ['question'],
68
69
  },
@@ -76,13 +77,13 @@ const tools = [
76
77
  properties: {
77
78
  contract_text: {
78
79
  type: 'string',
79
- maxLength: 10000,
80
- description: 'The contract text to review. Combined with standpoint must not exceed 10000 chars.',
80
+ maxLength: 30000,
81
+ description: 'The contract text to review. Combined with standpoint must not exceed 30000 chars.',
81
82
  },
82
83
  file_ref: { type: 'string', description: 'Local plaintext file path as alternative to contract_text.' },
83
84
  standpoint: {
84
85
  type: 'string',
85
- maxLength: 10000,
86
+ maxLength: 30000,
86
87
  description: 'Your review standpoint and requirements, e.g. "我是甲方(买方),请重点审查付款条款和违约责任".',
87
88
  },
88
89
  reviewer_name: { type: 'string', maxLength: 40, description: 'Reviewer name for the opinion header, e.g. "张律师".' },
@@ -97,7 +98,7 @@ const tools = [
97
98
  type: 'object',
98
99
  properties: {
99
100
  document_type: { type: 'string', description: 'Document type, e.g. "民事起诉状", "答辩状", "代理词".' },
100
- facts: { type: 'string', maxLength: 10000, description: 'Key facts and claims (max 10000 chars).' },
101
+ facts: { type: 'string', maxLength: 30000, description: 'Key facts and claims (max 30000 chars).' },
101
102
  case_file_refs: {
102
103
  type: 'array',
103
104
  items: { type: 'string' },
@@ -174,10 +175,11 @@ async function handleLegalQa(args) {
174
175
  assertConfigured(PROXY_BASE_URL, 'ACCURLEX_PROXY_BASE_URL is required');
175
176
 
176
177
  const question = asNonEmptyString(args.question, 'question');
177
- if (question.length > MAX_INPUT_CHARS) {
178
- throw withCode(new Error(`问题字数超出上限(${question.length}/${MAX_INPUT_CHARS})`), 'input_too_long');
179
- }
180
178
  const mode = args.mode === 'expert' ? 'expert' : 'deep';
179
+ const charLimit = mode === 'expert' ? MAX_INPUT_CHARS_PAID : MAX_INPUT_CHARS;
180
+ if (question.length > charLimit) {
181
+ throw withCode(new Error(`问题字数超出上限(${question.length}/${charLimit})`), 'input_too_long');
182
+ }
181
183
  const history = Array.isArray(args.history) ? args.history : [];
182
184
  const contextText = optionalString(args.context_text);
183
185
  const route = mode === 'expert' ? '/ask_stream' : '/ask_free_stream';
@@ -219,11 +221,11 @@ async function handleContractReview(args) {
219
221
  const standpoint = asNonEmptyString(args.standpoint, 'standpoint');
220
222
  const contractText = await resolveTextInput(args.contract_text, args.file_ref, 'contract_text');
221
223
 
222
- // Enforce combined character limit (aligned with website: 10000 chars total)
224
+ // Enforce combined character limit (contract review is always paid: 30000 chars)
223
225
  const totalLen = contractText.length + standpoint.length;
224
- if (totalLen > MAX_INPUT_CHARS) {
226
+ if (totalLen > MAX_INPUT_CHARS_PAID) {
225
227
  throw withCode(
226
- new Error(`合同文本+审查立场总字数超出上限(${totalLen}/${MAX_INPUT_CHARS}),请精简输入`),
228
+ new Error(`合同文本+审查立场总字数超出上限(${totalLen}/${MAX_INPUT_CHARS_PAID}),请精简输入`),
227
229
  'input_too_long',
228
230
  );
229
231
  }
@@ -262,8 +264,8 @@ async function handleDraftDocument(args) {
262
264
 
263
265
  const documentType = asNonEmptyString(args.document_type, 'document_type');
264
266
  const facts = asNonEmptyString(args.facts, 'facts');
265
- if (facts.length > MAX_INPUT_CHARS) {
266
- throw withCode(new Error(`事实描述字数超出上限(${facts.length}/${MAX_INPUT_CHARS})`), 'input_too_long');
267
+ if (facts.length > MAX_INPUT_CHARS_PAID) {
268
+ throw withCode(new Error(`事实描述字数超出上限(${facts.length}/${MAX_INPUT_CHARS_PAID})`), 'input_too_long');
267
269
  }
268
270
  const referenceTexts = await resolveManyTextFiles(args.case_file_refs);
269
271
  const styleText = optionalString(args.style_file_ref)