mcp-swiss 0.1.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/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +61 -0
- package/dist/modules/companies.d.ts +83 -0
- package/dist/modules/companies.js +156 -0
- package/dist/modules/geodata.d.ts +109 -0
- package/dist/modules/geodata.js +174 -0
- package/dist/modules/transport.d.ts +141 -0
- package/dist/modules/transport.js +134 -0
- package/dist/modules/weather.d.ts +50 -0
- package/dist/modules/weather.js +128 -0
- package/dist/utils/http.d.ts +2 -0
- package/dist/utils/http.js +27 -0
- package/package.json +64 -0
- package/src/index.ts +70 -0
- package/src/modules/companies.ts +154 -0
- package/src/modules/geodata.ts +179 -0
- package/src/modules/transport.ts +138 -0
- package/src/modules/weather.ts +133 -0
- package/src/utils/http.ts +26 -0
- package/tsconfig.json +15 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vikram Gorla
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# mcp-swiss 🏔️
|
|
2
|
+
|
|
3
|
+
[](https://github.com/vikramgorla/mcp-swiss/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/mcp-swiss)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://modelcontextprotocol.io)
|
|
7
|
+
|
|
8
|
+
Swiss open data MCP server for AI assistants. Zero API keys. Zero config. Just works.
|
|
9
|
+
|
|
10
|
+
## What is this?
|
|
11
|
+
|
|
12
|
+
`mcp-swiss` is a [Model Context Protocol](https://modelcontextprotocol.io) server that gives AI assistants (Claude, Cursor, Cline, etc.) direct access to Swiss open data:
|
|
13
|
+
|
|
14
|
+
- 🚆 **Transport** — SBB trains, PostBus, trams, live departures, journey planning
|
|
15
|
+
- 🌤️ **Weather** — MeteoSwiss live conditions + historical data
|
|
16
|
+
- 🌊 **Hydrology** — BAFU river and lake levels (great for Aare swimming!)
|
|
17
|
+
- 🗺️ **Geodata** — swisstopo geocoding, solar potential, geographic layers
|
|
18
|
+
- 🏢 **Companies** — ZEFIX federal registry, all 700K+ Swiss companies
|
|
19
|
+
|
|
20
|
+
**22 tools. No API keys. No registration. No server to run.**
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx mcp-swiss
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Configuration
|
|
33
|
+
|
|
34
|
+
### Claude Desktop
|
|
35
|
+
|
|
36
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mcpServers": {
|
|
41
|
+
"swiss": {
|
|
42
|
+
"command": "npx",
|
|
43
|
+
"args": ["mcp-swiss"]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Restart Claude Desktop after saving.
|
|
50
|
+
|
|
51
|
+
### Cursor
|
|
52
|
+
|
|
53
|
+
Create or edit `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` globally):
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"mcpServers": {
|
|
58
|
+
"swiss": {
|
|
59
|
+
"command": "npx",
|
|
60
|
+
"args": ["mcp-swiss"]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Cline (VSCode)
|
|
67
|
+
|
|
68
|
+
Open `settings.json` and add:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"cline.mcpServers": {
|
|
73
|
+
"swiss": {
|
|
74
|
+
"command": "npx",
|
|
75
|
+
"args": ["mcp-swiss"]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Demo Prompts
|
|
84
|
+
|
|
85
|
+
Once connected, try asking your AI:
|
|
86
|
+
|
|
87
|
+
- *"Next 5 trains from ZĂĽrich HB to Geneva right now"*
|
|
88
|
+
- *"Is the Aare in Bern warm enough to swim? What's the water level?"*
|
|
89
|
+
- *"Weather in Lugano vs ZĂĽrich today"*
|
|
90
|
+
- *"Find all companies with 'blockchain' in their name registered in Zug"*
|
|
91
|
+
- *"What's the solar potential of Bundesplatz 3, Bern?"*
|
|
92
|
+
- *"Live departures from Bern HB in the next 30 minutes"*
|
|
93
|
+
- *"Plan my Saturday: train to Interlaken, check weather, find the nearest SBB station"*
|
|
94
|
+
- *"What rivers are near Thun and what are their current water levels?"*
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Tools
|
|
99
|
+
|
|
100
|
+
Full specifications for all tools: [`docs/tool-specs.md`](docs/tool-specs.md) | Machine-readable: [`docs/tools.schema.json`](docs/tools.schema.json)
|
|
101
|
+
|
|
102
|
+
### 🚆 Transport (5 tools)
|
|
103
|
+
| Tool | Description |
|
|
104
|
+
|------|-------------|
|
|
105
|
+
| `search_stations` | Find stations/stops by name or location |
|
|
106
|
+
| `get_connections` | Journey planner between any two points |
|
|
107
|
+
| `get_departures` | Live departures from a station |
|
|
108
|
+
| `get_arrivals` | Live arrivals at a station |
|
|
109
|
+
| `get_nearby_stations` | Stations near coordinates |
|
|
110
|
+
|
|
111
|
+
### 🌤️ Weather & Hydrology (6 tools)
|
|
112
|
+
| Tool | Description |
|
|
113
|
+
|------|-------------|
|
|
114
|
+
| `get_weather` | Current conditions at a MeteoSwiss station |
|
|
115
|
+
| `list_weather_stations` | All ~160 MeteoSwiss stations with metadata |
|
|
116
|
+
| `get_weather_history` | Historical weather data (up to 32 days) |
|
|
117
|
+
| `get_water_level` | River/lake level + temperature (BAFU) |
|
|
118
|
+
| `list_hydro_stations` | All 400+ hydrological monitoring stations |
|
|
119
|
+
| `get_water_history` | Historical hydrology data |
|
|
120
|
+
|
|
121
|
+
### 🗺️ Geodata / swisstopo (6 tools)
|
|
122
|
+
| Tool | Description |
|
|
123
|
+
|------|-------------|
|
|
124
|
+
| `geocode` | Swiss address → coordinates |
|
|
125
|
+
| `reverse_geocode` | Coordinates → Swiss address |
|
|
126
|
+
| `search_places` | Swiss place names, mountains, lakes, features |
|
|
127
|
+
| `get_solar_potential` | Rooftop solar irradiation at a location |
|
|
128
|
+
| `identify_location` | All geographic data layers at a point |
|
|
129
|
+
| `get_municipality` | Municipality info by name |
|
|
130
|
+
|
|
131
|
+
### 🏢 Companies / ZEFIX (5 tools)
|
|
132
|
+
| Tool | Description |
|
|
133
|
+
|------|-------------|
|
|
134
|
+
| `search_companies` | Search by name, canton, legal form |
|
|
135
|
+
| `get_company` | Full company details by ZEFIX `ehraid` (from search results) |
|
|
136
|
+
| `search_companies_by_address` | Companies registered at an address |
|
|
137
|
+
| `list_cantons` | All 26 Swiss cantons |
|
|
138
|
+
| `list_legal_forms` | AG, GmbH, and all Swiss legal forms |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Data Sources
|
|
143
|
+
|
|
144
|
+
All official Swiss open data — no API keys required:
|
|
145
|
+
|
|
146
|
+
| Source | Data | API |
|
|
147
|
+
|--------|------|-----|
|
|
148
|
+
| [transport.opendata.ch](https://transport.opendata.ch) | SBB, PostBus, trams | REST |
|
|
149
|
+
| [api.existenz.ch](https://api.existenz.ch) | MeteoSwiss weather + BAFU hydrology | REST |
|
|
150
|
+
| [api3.geo.admin.ch](https://api3.geo.admin.ch) | swisstopo federal geodata | REST |
|
|
151
|
+
| [zefix.admin.ch](https://www.zefix.admin.ch) | Federal company registry | REST |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## For contributors
|
|
156
|
+
|
|
157
|
+
mcp-swiss uses [Speckit](https://github.com/jmanhype/speckit) — a spec-driven development workflow.
|
|
158
|
+
Every new tool or module starts with a spec in `specs/`, not code.
|
|
159
|
+
|
|
160
|
+
See [`CONTRIBUTING.md`](.github/CONTRIBUTING.md) for the full workflow including:
|
|
161
|
+
- How to add a new tool (spec → plan → implement → test)
|
|
162
|
+
- Testing requirements (unit + integration + MCP protocol)
|
|
163
|
+
- Code style and ESLint rules
|
|
164
|
+
- Branch naming and PR process
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Requirements
|
|
169
|
+
|
|
170
|
+
- Node.js 18+
|
|
171
|
+
- No API keys or accounts needed
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
7
|
+
const transport_js_1 = require("./modules/transport.js");
|
|
8
|
+
const weather_js_1 = require("./modules/weather.js");
|
|
9
|
+
const geodata_js_1 = require("./modules/geodata.js");
|
|
10
|
+
const companies_js_1 = require("./modules/companies.js");
|
|
11
|
+
const server = new index_js_1.Server({ name: "mcp-swiss", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
12
|
+
const allTools = [
|
|
13
|
+
...transport_js_1.transportTools,
|
|
14
|
+
...weather_js_1.weatherTools,
|
|
15
|
+
...geodata_js_1.geodataTools,
|
|
16
|
+
...companies_js_1.companiesTools,
|
|
17
|
+
];
|
|
18
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
19
|
+
tools: allTools,
|
|
20
|
+
}));
|
|
21
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
22
|
+
const { name, arguments: args } = request.params;
|
|
23
|
+
const safeArgs = (args ?? {});
|
|
24
|
+
try {
|
|
25
|
+
let result;
|
|
26
|
+
if (transport_js_1.transportTools.some((t) => t.name === name)) {
|
|
27
|
+
result = await (0, transport_js_1.handleTransport)(name, safeArgs);
|
|
28
|
+
}
|
|
29
|
+
else if (weather_js_1.weatherTools.some((t) => t.name === name)) {
|
|
30
|
+
result = await (0, weather_js_1.handleWeather)(name, safeArgs);
|
|
31
|
+
}
|
|
32
|
+
else if (geodata_js_1.geodataTools.some((t) => t.name === name)) {
|
|
33
|
+
result = await (0, geodata_js_1.handleGeodata)(name, safeArgs);
|
|
34
|
+
}
|
|
35
|
+
else if (companies_js_1.companiesTools.some((t) => t.name === name)) {
|
|
36
|
+
result = await (0, companies_js_1.handleCompanies)(name, safeArgs);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
content: [{ type: "text", text: result }],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
47
|
+
return {
|
|
48
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
49
|
+
isError: true,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
async function main() {
|
|
54
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
55
|
+
await server.connect(transport);
|
|
56
|
+
process.stderr.write("mcp-swiss running on stdio\n");
|
|
57
|
+
}
|
|
58
|
+
main().catch((err) => {
|
|
59
|
+
process.stderr.write(`Fatal: ${err}\n`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export declare const companiesTools: ({
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: string;
|
|
6
|
+
required: string[];
|
|
7
|
+
properties: {
|
|
8
|
+
name: {
|
|
9
|
+
type: string;
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
canton: {
|
|
13
|
+
type: string;
|
|
14
|
+
description: string;
|
|
15
|
+
};
|
|
16
|
+
legal_form: {
|
|
17
|
+
type: string;
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
20
|
+
limit: {
|
|
21
|
+
type: string;
|
|
22
|
+
description: string;
|
|
23
|
+
};
|
|
24
|
+
ehraid?: undefined;
|
|
25
|
+
address?: undefined;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
} | {
|
|
29
|
+
name: string;
|
|
30
|
+
description: string;
|
|
31
|
+
inputSchema: {
|
|
32
|
+
type: string;
|
|
33
|
+
required: string[];
|
|
34
|
+
properties: {
|
|
35
|
+
ehraid: {
|
|
36
|
+
type: string;
|
|
37
|
+
description: string;
|
|
38
|
+
};
|
|
39
|
+
name?: undefined;
|
|
40
|
+
canton?: undefined;
|
|
41
|
+
legal_form?: undefined;
|
|
42
|
+
limit?: undefined;
|
|
43
|
+
address?: undefined;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
} | {
|
|
47
|
+
name: string;
|
|
48
|
+
description: string;
|
|
49
|
+
inputSchema: {
|
|
50
|
+
type: string;
|
|
51
|
+
required: string[];
|
|
52
|
+
properties: {
|
|
53
|
+
address: {
|
|
54
|
+
type: string;
|
|
55
|
+
description: string;
|
|
56
|
+
};
|
|
57
|
+
limit: {
|
|
58
|
+
type: string;
|
|
59
|
+
description: string;
|
|
60
|
+
};
|
|
61
|
+
name?: undefined;
|
|
62
|
+
canton?: undefined;
|
|
63
|
+
legal_form?: undefined;
|
|
64
|
+
ehraid?: undefined;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
} | {
|
|
68
|
+
name: string;
|
|
69
|
+
description: string;
|
|
70
|
+
inputSchema: {
|
|
71
|
+
type: string;
|
|
72
|
+
properties: {
|
|
73
|
+
name?: undefined;
|
|
74
|
+
canton?: undefined;
|
|
75
|
+
legal_form?: undefined;
|
|
76
|
+
limit?: undefined;
|
|
77
|
+
ehraid?: undefined;
|
|
78
|
+
address?: undefined;
|
|
79
|
+
};
|
|
80
|
+
required?: undefined;
|
|
81
|
+
};
|
|
82
|
+
})[];
|
|
83
|
+
export declare function handleCompanies(name: string, args: Record<string, unknown>): Promise<string>;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.companiesTools = void 0;
|
|
4
|
+
exports.handleCompanies = handleCompanies;
|
|
5
|
+
const http_js_1 = require("../utils/http.js");
|
|
6
|
+
const BASE = "https://www.zefix.admin.ch/ZefixREST/api/v1";
|
|
7
|
+
exports.companiesTools = [
|
|
8
|
+
{
|
|
9
|
+
name: "search_companies",
|
|
10
|
+
description: "Search Swiss company registry (ZEFIX) by name, canton, or legal form",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: "object",
|
|
13
|
+
required: ["name"],
|
|
14
|
+
properties: {
|
|
15
|
+
name: { type: "string", description: "Company name or partial name to search" },
|
|
16
|
+
canton: { type: "string", description: "Canton abbreviation (e.g. ZH, BE, GE, ZG)" },
|
|
17
|
+
legal_form: { type: "string", description: "Legal form code (e.g. 0106=GmbH, 0101=AG)" },
|
|
18
|
+
limit: { type: "number", description: "Max results (default: 20)" },
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: "get_company",
|
|
24
|
+
description: "Get full details of a Swiss company by its ZEFIX internal ID (ehraid). Use search_companies first to find the ehraid — it is returned in company search results.",
|
|
25
|
+
inputSchema: {
|
|
26
|
+
type: "object",
|
|
27
|
+
required: ["ehraid"],
|
|
28
|
+
properties: {
|
|
29
|
+
ehraid: { type: "number", description: "Company internal ZEFIX ID (ehraid integer, e.g. 119283). Returned by search_companies." },
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "search_companies_by_address",
|
|
35
|
+
description: "Search Swiss companies registered at a specific address or locality",
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: "object",
|
|
38
|
+
required: ["address"],
|
|
39
|
+
properties: {
|
|
40
|
+
address: { type: "string", description: "Address or locality name" },
|
|
41
|
+
limit: { type: "number", description: "Max results (default: 20)" },
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "list_cantons",
|
|
47
|
+
description: "List all Swiss cantons with their codes",
|
|
48
|
+
inputSchema: {
|
|
49
|
+
type: "object",
|
|
50
|
+
properties: {},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "list_legal_forms",
|
|
55
|
+
description: "List all Swiss company legal forms (AG, GmbH, etc.)",
|
|
56
|
+
inputSchema: {
|
|
57
|
+
type: "object",
|
|
58
|
+
properties: {},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
async function handleCompanies(name, args) {
|
|
63
|
+
switch (name) {
|
|
64
|
+
case "search_companies": {
|
|
65
|
+
const body = {
|
|
66
|
+
name: args.name,
|
|
67
|
+
maxEntries: args.limit ?? 20,
|
|
68
|
+
languageKey: "en",
|
|
69
|
+
};
|
|
70
|
+
if (args.canton)
|
|
71
|
+
body.cantonAbbreviation = [args.canton];
|
|
72
|
+
if (args.legal_form)
|
|
73
|
+
body.legalFormCode = args.legal_form;
|
|
74
|
+
const response = await fetch(`${BASE}/firm/search.json`, {
|
|
75
|
+
method: "POST",
|
|
76
|
+
headers: { "Content-Type": "application/json", "Accept": "application/json" },
|
|
77
|
+
body: JSON.stringify(body),
|
|
78
|
+
});
|
|
79
|
+
if (response.status === 404) {
|
|
80
|
+
return JSON.stringify({ companies: [], hasMoreResults: false }, null, 2);
|
|
81
|
+
}
|
|
82
|
+
if (!response.ok)
|
|
83
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
84
|
+
const data = await response.json();
|
|
85
|
+
if (data.error)
|
|
86
|
+
return JSON.stringify({ companies: [], hasMoreResults: false }, null, 2);
|
|
87
|
+
return JSON.stringify({ companies: data.list ?? [], hasMoreResults: data.hasMoreResults ?? false }, null, 2);
|
|
88
|
+
}
|
|
89
|
+
case "get_company": {
|
|
90
|
+
// ZEFIX firm/{id}.json uses the internal ehraid integer (not CHE uid)
|
|
91
|
+
const ehraid = args.ehraid;
|
|
92
|
+
const url = `${BASE}/firm/${ehraid}.json`;
|
|
93
|
+
const data = await (0, http_js_1.fetchJSON)(url);
|
|
94
|
+
return JSON.stringify(data, null, 2);
|
|
95
|
+
}
|
|
96
|
+
case "search_companies_by_address": {
|
|
97
|
+
const body = {
|
|
98
|
+
name: args.address,
|
|
99
|
+
maxEntries: args.limit ?? 20,
|
|
100
|
+
languageKey: "en",
|
|
101
|
+
};
|
|
102
|
+
const response = await fetch(`${BASE}/firm/search.json`, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: { "Content-Type": "application/json", "Accept": "application/json" },
|
|
105
|
+
body: JSON.stringify(body),
|
|
106
|
+
});
|
|
107
|
+
if (response.status === 404)
|
|
108
|
+
return JSON.stringify({ companies: [], hasMoreResults: false }, null, 2);
|
|
109
|
+
if (!response.ok)
|
|
110
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
111
|
+
const data = await response.json();
|
|
112
|
+
if (data.error)
|
|
113
|
+
return JSON.stringify({ companies: [], hasMoreResults: false }, null, 2);
|
|
114
|
+
return JSON.stringify({ companies: data.list ?? [], hasMoreResults: data.hasMoreResults ?? false }, null, 2);
|
|
115
|
+
}
|
|
116
|
+
case "list_cantons": {
|
|
117
|
+
// ZEFIX /cantons and /legalForms endpoints require authentication (403).
|
|
118
|
+
// Return hardcoded authoritative list instead.
|
|
119
|
+
const cantons = [
|
|
120
|
+
{ code: "AG", name: "Aargau" }, { code: "AI", name: "Appenzell Innerrhoden" },
|
|
121
|
+
{ code: "AR", name: "Appenzell Ausserrhoden" }, { code: "BE", name: "Bern" },
|
|
122
|
+
{ code: "BL", name: "Basel-Landschaft" }, { code: "BS", name: "Basel-Stadt" },
|
|
123
|
+
{ code: "FR", name: "Fribourg" }, { code: "GE", name: "Geneva" },
|
|
124
|
+
{ code: "GL", name: "Glarus" }, { code: "GR", name: "GraubĂĽnden" },
|
|
125
|
+
{ code: "JU", name: "Jura" }, { code: "LU", name: "Lucerne" },
|
|
126
|
+
{ code: "NE", name: "Neuchâtel" }, { code: "NW", name: "Nidwalden" },
|
|
127
|
+
{ code: "OW", name: "Obwalden" }, { code: "SG", name: "St. Gallen" },
|
|
128
|
+
{ code: "SH", name: "Schaffhausen" }, { code: "SO", name: "Solothurn" },
|
|
129
|
+
{ code: "SZ", name: "Schwyz" }, { code: "TG", name: "Thurgau" },
|
|
130
|
+
{ code: "TI", name: "Ticino" }, { code: "UR", name: "Uri" },
|
|
131
|
+
{ code: "VD", name: "Vaud" }, { code: "VS", name: "Valais" },
|
|
132
|
+
{ code: "ZG", name: "Zug" }, { code: "ZH", name: "ZĂĽrich" },
|
|
133
|
+
];
|
|
134
|
+
return JSON.stringify(cantons, null, 2);
|
|
135
|
+
}
|
|
136
|
+
case "list_legal_forms": {
|
|
137
|
+
// ZEFIX /legalForms requires authentication (403). Return common Swiss legal forms.
|
|
138
|
+
const forms = [
|
|
139
|
+
{ code: "0101", name: "Einzelunternehmen", nameEn: "Sole proprietorship" },
|
|
140
|
+
{ code: "0103", name: "Kollektivgesellschaft", nameEn: "General partnership" },
|
|
141
|
+
{ code: "0104", name: "Kommanditgesellschaft", nameEn: "Limited partnership" },
|
|
142
|
+
{ code: "0105", name: "Aktiengesellschaft (AG)", nameEn: "Corporation (AG)" },
|
|
143
|
+
{ code: "0106", name: "Gesellschaft mit beschränkter Haftung (GmbH)", nameEn: "Limited liability company (GmbH)" },
|
|
144
|
+
{ code: "0107", name: "Genossenschaft", nameEn: "Cooperative" },
|
|
145
|
+
{ code: "0108", name: "Verein", nameEn: "Association" },
|
|
146
|
+
{ code: "0109", name: "Stiftung", nameEn: "Foundation" },
|
|
147
|
+
{ code: "0110", name: "Kommanditaktiengesellschaft", nameEn: "Partnership limited by shares" },
|
|
148
|
+
{ code: "0113", name: "Filiale ausländischer Gesellschaft", nameEn: "Branch of foreign company" },
|
|
149
|
+
{ code: "0114", name: "Institut des öffentlichen Rechts", nameEn: "Public law institution" },
|
|
150
|
+
];
|
|
151
|
+
return JSON.stringify(forms, null, 2);
|
|
152
|
+
}
|
|
153
|
+
default:
|
|
154
|
+
throw new Error(`Unknown companies tool: ${name}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export declare const geodataTools: ({
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: string;
|
|
6
|
+
required: string[];
|
|
7
|
+
properties: {
|
|
8
|
+
address: {
|
|
9
|
+
type: string;
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
lat?: undefined;
|
|
13
|
+
lng?: undefined;
|
|
14
|
+
query?: undefined;
|
|
15
|
+
type?: undefined;
|
|
16
|
+
layers?: undefined;
|
|
17
|
+
name?: undefined;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
} | {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
inputSchema: {
|
|
24
|
+
type: string;
|
|
25
|
+
required: string[];
|
|
26
|
+
properties: {
|
|
27
|
+
lat: {
|
|
28
|
+
type: string;
|
|
29
|
+
description: string;
|
|
30
|
+
};
|
|
31
|
+
lng: {
|
|
32
|
+
type: string;
|
|
33
|
+
description: string;
|
|
34
|
+
};
|
|
35
|
+
address?: undefined;
|
|
36
|
+
query?: undefined;
|
|
37
|
+
type?: undefined;
|
|
38
|
+
layers?: undefined;
|
|
39
|
+
name?: undefined;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
} | {
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: string;
|
|
47
|
+
required: string[];
|
|
48
|
+
properties: {
|
|
49
|
+
query: {
|
|
50
|
+
type: string;
|
|
51
|
+
description: string;
|
|
52
|
+
};
|
|
53
|
+
type: {
|
|
54
|
+
type: string;
|
|
55
|
+
description: string;
|
|
56
|
+
};
|
|
57
|
+
address?: undefined;
|
|
58
|
+
lat?: undefined;
|
|
59
|
+
lng?: undefined;
|
|
60
|
+
layers?: undefined;
|
|
61
|
+
name?: undefined;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
} | {
|
|
65
|
+
name: string;
|
|
66
|
+
description: string;
|
|
67
|
+
inputSchema: {
|
|
68
|
+
type: string;
|
|
69
|
+
required: string[];
|
|
70
|
+
properties: {
|
|
71
|
+
lat: {
|
|
72
|
+
type: string;
|
|
73
|
+
description: string;
|
|
74
|
+
};
|
|
75
|
+
lng: {
|
|
76
|
+
type: string;
|
|
77
|
+
description: string;
|
|
78
|
+
};
|
|
79
|
+
layers: {
|
|
80
|
+
type: string;
|
|
81
|
+
description: string;
|
|
82
|
+
};
|
|
83
|
+
address?: undefined;
|
|
84
|
+
query?: undefined;
|
|
85
|
+
type?: undefined;
|
|
86
|
+
name?: undefined;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
} | {
|
|
90
|
+
name: string;
|
|
91
|
+
description: string;
|
|
92
|
+
inputSchema: {
|
|
93
|
+
type: string;
|
|
94
|
+
required: string[];
|
|
95
|
+
properties: {
|
|
96
|
+
name: {
|
|
97
|
+
type: string;
|
|
98
|
+
description: string;
|
|
99
|
+
};
|
|
100
|
+
address?: undefined;
|
|
101
|
+
lat?: undefined;
|
|
102
|
+
lng?: undefined;
|
|
103
|
+
query?: undefined;
|
|
104
|
+
type?: undefined;
|
|
105
|
+
layers?: undefined;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
})[];
|
|
109
|
+
export declare function handleGeodata(name: string, args: Record<string, unknown>): Promise<string>;
|