poi-plugin-mcp 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 ADDED
@@ -0,0 +1,76 @@
1
+ # poi-plugin-mcp
2
+
3
+ Poi plugin that starts a local HTTP bridge inside Poi so CLI/MCP agents can read current KanColle data.
4
+
5
+ This package is maintained inside the repository root. Do not install it manually from this folder unless you know what you are doing; prefer the root setup flow.
6
+
7
+ ## Install From Repo Root
8
+
9
+ ```powershell
10
+ npm install
11
+ npm run install:poi
12
+ ```
13
+
14
+ Then restart Poi and enable `MCP 数据桥` / `KanColle Data Bridge` if needed.
15
+
16
+ The installer creates:
17
+
18
+ ```text
19
+ %APPDATA%\poi\plugins\node_modules\poi-plugin-mcp -> <repo>\packages\poi-plugin-mcp
20
+ ```
21
+
22
+ ## Settings
23
+
24
+ The Poi plugin settings panel supports:
25
+
26
+ - changing the HTTP port, saved in `~/.poi-mcp/settings.json`
27
+ - manually starting and stopping the local bridge
28
+
29
+ The default port is `17777`.
30
+
31
+ ## HTTP Endpoints
32
+
33
+ | Endpoint | Data |
34
+ |---|---|
35
+ | `/health` | Bridge status |
36
+ | `/basic` | Admiral profile |
37
+ | `/fleets` | Raw Poi fleet data |
38
+ | `/ships` | Raw owned ship instance data |
39
+ | `/equipment` | Raw owned equipment instance data |
40
+ | `/resources` | Resource array |
41
+ | `/quests` | Active quests and quest records |
42
+ | `/airbase` | Land base air squadron data |
43
+ | `/names` | Ship, equipment, and mission name maps |
44
+ | `/master` | Master ship, equipment, ship type, equipment type, and mission data |
45
+ | `/event` | Event ship tag definitions plus owned ships' current sally area |
46
+ | `/planner` | Ship Info deck planner areas and ship assignments |
47
+ | `/all` | Combined basic runtime data |
48
+
49
+ ## MCP Endpoint
50
+
51
+ The same local server also exposes a JSON-RPC MCP endpoint:
52
+
53
+ ```text
54
+ POST http://127.0.0.1:17777/mcp
55
+ ```
56
+
57
+ It supports `initialize`, `ping`, `resources/list`, `resources/read`,
58
+ `tools/list`, and `tools/call`. Resource URIs mirror the HTTP endpoints,
59
+ including `poi://ships`, `poi://equipment`, `poi://resources`, `poi://master`,
60
+ `poi://event`, and `poi://planner`.
61
+
62
+ Available tools:
63
+
64
+ - `get_fleet_status`
65
+ - `search_ships`
66
+ - `search_equipment`
67
+ - `get_resources`
68
+ - `get_all`
69
+
70
+ ## Verification
71
+
72
+ From the repo root:
73
+
74
+ ```powershell
75
+ npm run test:plugin
76
+ ```
package/index.js ADDED
@@ -0,0 +1,25 @@
1
+ const { createBridgeController } = require('./lib/bridge-controller')
2
+ const { createSettingsClass } = require('./lib/settings-view')
3
+
4
+ const controller = createBridgeController()
5
+ const settingsClass = createSettingsClass(controller)
6
+
7
+ function pluginDidLoad() {
8
+ controller.load().catch((error) => {
9
+ console.error('[poi-plugin-mcp] Failed to start:', error.message)
10
+ })
11
+ }
12
+
13
+ function pluginWillUnload() {
14
+ controller.unload().catch((error) => {
15
+ console.error('[poi-plugin-mcp] Failed to stop:', error.message)
16
+ })
17
+ }
18
+
19
+ module.exports = {
20
+ pluginDidLoad,
21
+ pluginWillUnload,
22
+ settingClass: settingsClass,
23
+ settingsClass,
24
+ _controller: controller,
25
+ }
@@ -0,0 +1,118 @@
1
+ const { createPoiDataBridge } = require('./poi-http-bridge')
2
+ const {
3
+ DEFAULT_SETTINGS_FILE,
4
+ loadSettings,
5
+ normalizeSettings,
6
+ saveSettings,
7
+ } = require('./settings')
8
+
9
+ function createBridgeController(options = {}) {
10
+ const settingsPath = options.settingsPath || DEFAULT_SETTINGS_FILE
11
+ const logger = options.logger || console
12
+ const createBridge = options.createBridge || createPoiDataBridge
13
+
14
+ let settings = loadSettings(settingsPath)
15
+ let bridge = null
16
+ let pending = Promise.resolve()
17
+
18
+ function enqueue(action) {
19
+ pending = pending.then(action, action)
20
+ return pending
21
+ }
22
+
23
+ function createCurrentBridge() {
24
+ return createBridge({
25
+ getStore: options.getStore,
26
+ port: settings.port,
27
+ portFile: options.portFile,
28
+ logger,
29
+ })
30
+ }
31
+
32
+ async function ensureStarted() {
33
+ if (!bridge) {
34
+ bridge = createCurrentBridge()
35
+ }
36
+ await bridge.start()
37
+ }
38
+
39
+ async function stopCurrentBridge() {
40
+ if (!bridge) return
41
+
42
+ const runningBridge = bridge
43
+ bridge = null
44
+ await runningBridge.stop()
45
+ }
46
+
47
+ function persist(nextSettings) {
48
+ settings = saveSettings(normalizeSettings(nextSettings), settingsPath)
49
+ return settings
50
+ }
51
+
52
+ return {
53
+ load() {
54
+ return enqueue(async () => {
55
+ settings = loadSettings(settingsPath)
56
+ if (settings.enabled) await ensureStarted()
57
+ })
58
+ },
59
+
60
+ unload() {
61
+ return enqueue(async () => {
62
+ await stopCurrentBridge()
63
+ })
64
+ },
65
+
66
+ startBridge() {
67
+ return enqueue(async () => {
68
+ persist({ ...settings, enabled: true })
69
+ await ensureStarted()
70
+ })
71
+ },
72
+
73
+ stopBridge() {
74
+ return enqueue(async () => {
75
+ persist({ ...settings, enabled: false })
76
+ await stopCurrentBridge()
77
+ })
78
+ },
79
+
80
+ applySettings(nextSettings) {
81
+ return enqueue(async () => {
82
+ const normalized = normalizeSettings({ ...settings, ...nextSettings })
83
+ const portChanged = normalized.port !== settings.port
84
+ const enabledChanged = normalized.enabled !== settings.enabled
85
+
86
+ persist(normalized)
87
+
88
+ if (!settings.enabled) {
89
+ await stopCurrentBridge()
90
+ return
91
+ }
92
+
93
+ if (portChanged || enabledChanged || !bridge) {
94
+ await stopCurrentBridge()
95
+ await ensureStarted()
96
+ }
97
+ })
98
+ },
99
+
100
+ getSettings() {
101
+ return { ...settings }
102
+ },
103
+
104
+ getStatus() {
105
+ const actualPort = bridge ? bridge.getPort() : 0
106
+ return {
107
+ enabled: settings.enabled,
108
+ running: actualPort > 0,
109
+ port: settings.port,
110
+ actualPort,
111
+ }
112
+ },
113
+ }
114
+ }
115
+
116
+ module.exports = {
117
+ createBridgeController,
118
+ }