@perenia/mcp 0.1.0 → 0.2.0

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.
package/README.md CHANGED
@@ -36,7 +36,8 @@ against a dev instance).
36
36
 
37
37
  | Tool | What it does |
38
38
  |---|---|
39
- | `search_companies` | Text + filtered search (location, NAF activity, size, financials, financial-score grade, decision-maker age, geo radius). Compact summaries, paginated. |
39
+ | `search_companies` | Text + filtered search (location, NAF activity, size, financials, financial-score grade, decision-maker age, geo radius). Compact summaries, paginated — or, with `columns`, rows holding exactly the requested columns (same ids as the web table's templates and CSV export). |
40
+ | `list_columns` | The column catalogue for `search_companies` `columns`, grouped, with each column's kind and fields. No quota cost. |
40
41
  | `get_company` | Full profile by SIREN, including multi-year financial history. |
41
42
  | `get_company_officers` | Officer roster (names and roles — no personal data). |
42
43
  | `get_network_neighbours` | Companies sharing an officer network (holdings, sister companies). |
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ if (!apiKey) {
10
10
  process.exit(1);
11
11
  }
12
12
  const baseUrl = (process.env.PERENIA_API_URL ?? 'https://api.perenia.ai').replace(/\/$/, '');
13
- const server = new McpServer({ name: 'perenia', version: '0.1.0' });
13
+ const server = new McpServer({ name: 'perenia', version: '0.2.0' });
14
14
  registerTools(server, new ApiClient({ baseUrl, apiKey }));
15
15
  await server.connect(new StdioServerTransport());
16
16
  console.error(`perenia-mcp ready (${baseUrl})`);
package/dist/tools.js CHANGED
@@ -55,20 +55,40 @@ async function guarded(fn) {
55
55
  }
56
56
  export function registerTools(server, api) {
57
57
  server.registerTool('search_companies', {
58
- description: 'Search ~3.5M French companies by text query and/or filters (location, activity, size, financials, decision-maker age, financial-score grade). Returns compact summaries — use get_company for full detail. Data refreshes daily.',
58
+ description: 'Search ~3.5M French companies by text query and/or filters (location, activity, size, financials, decision-maker age, financial-score grade). Returns compact summaries, or with `columns` — one row per company holding exactly the requested columns (ids from list_columns). Use get_company for full detail. Data refreshes daily.',
59
59
  inputSchema: {
60
60
  ...searchFiltersShape,
61
+ columns: z
62
+ .array(z.string())
63
+ .min(1)
64
+ .max(40)
65
+ .optional()
66
+ .describe('Ordered column ids from list_columns, e.g. ["company", "turnover", "netProfit", "founded"]. When set, results are rows keyed by column id (siren first; a code column also carries <id>_label) instead of compact summaries — pick the columns you need for a table or a comparison.'),
61
67
  page: z.number().int().min(1).max(100).optional().describe('Default 1'),
62
68
  per_page: z.number().int().min(1).max(50).optional().describe('Default 10'),
63
69
  },
64
70
  }, (args) => guarded(async () => {
65
- const { page, per_page, ...filters } = args;
71
+ const { page, per_page, columns, ...filters } = args;
66
72
  const res = (await api.post('/v1/companies/search', {
67
73
  ...toFilterState(filters),
74
+ ...(columns ? { columns } : {}),
68
75
  page: page ?? 1,
69
76
  perPage: per_page ?? 10,
70
77
  }));
71
- return ok({ total: res.total, page: res.page, per_page: res.per_page, companies: res.data.map(trimSummary) });
78
+ const paging = { total: res.total, page: res.page, per_page: res.per_page };
79
+ if (res.rows)
80
+ return ok({ ...paging, columns: res.columns, rows: res.rows });
81
+ return ok({ ...paging, companies: (res.data ?? []).map(trimSummary) });
82
+ }));
83
+ server.registerTool('list_columns', {
84
+ description: 'The column catalogue accepted by search_companies `columns`, grouped (profile, location, people, financials, score, network) with each column\'s value kind and the fields it reads. Cheap: no quota cost.',
85
+ inputSchema: {},
86
+ }, () => guarded(async () => {
87
+ const res = (await api.get('/v1/columns'));
88
+ const groups = {};
89
+ for (const { group, ...column } of res.columns)
90
+ (groups[group] ??= []).push(column);
91
+ return ok({ groups });
72
92
  }));
73
93
  server.registerTool('get_company', {
74
94
  description: 'Full profile of one company by SIREN: identity, location, activity descriptions, network counts, financial score, and multi-year financial history.',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perenia/mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "MCP server for the Perenia Partner API — search and analyze French companies from any MCP client",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",