MCP server at POST /mcp (official SDK, stateless Streamable HTTP) (#11)
CI / build + unit (push) Successful in 1m6s
CI / build + unit (push) Successful in 1m6s
This commit was merged in pull request #11.
This commit is contained in:
@@ -1,62 +1,20 @@
|
||||
import { create, fromBinary, toBinary } from '@bufbuild/protobuf';
|
||||
import * as P from '@meshtastic/protobufs';
|
||||
import * as net from 'node:net';
|
||||
import type { AddressInfo } from 'node:net';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { BROADCAST_ADDR, extractFrames, frame } from './codec.js';
|
||||
import {
|
||||
KAMIL_NUM,
|
||||
kamilNodeInfo,
|
||||
nodeInfoFrame,
|
||||
startBridge,
|
||||
waitFor,
|
||||
} from './fake-bridge.js';
|
||||
import { MeshService } from './mesh.service.js';
|
||||
|
||||
function startBridge(onSocket?: (s: net.Socket) => void): Promise<{
|
||||
port: number;
|
||||
sockets: net.Socket[];
|
||||
close: () => void;
|
||||
}> {
|
||||
const sockets: net.Socket[] = [];
|
||||
const server = net.createServer((socket) => {
|
||||
onSocket?.(socket); // attached at accept time, before any data can arrive
|
||||
sockets.push(socket);
|
||||
});
|
||||
return new Promise((resolve) => {
|
||||
server.listen(0, '127.0.0.1', () => {
|
||||
resolve({
|
||||
port: (server.address() as AddressInfo).port,
|
||||
sockets,
|
||||
close: () => server.close(),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function waitFor(
|
||||
cond: () => boolean | Promise<boolean>,
|
||||
timeoutMs = 5000,
|
||||
): Promise<void> {
|
||||
const t0 = Date.now();
|
||||
while (!(await cond())) {
|
||||
if (Date.now() - t0 > timeoutMs) throw new Error('timed out waiting');
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
}
|
||||
}
|
||||
|
||||
function nodeInfoFrame(
|
||||
num: number,
|
||||
fields?: Partial<P.Mesh.NodeInfo>,
|
||||
): Uint8Array {
|
||||
const ni = create(P.Mesh.NodeInfoSchema, { num, ...fields });
|
||||
return frame(
|
||||
toBinary(
|
||||
P.Mesh.FromRadioSchema,
|
||||
create(P.Mesh.FromRadioSchema, {
|
||||
payloadVariant: { case: 'nodeInfo', value: ni },
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// live position update: POSITION_APP packet with a serialized Position in Data.payload
|
||||
function positionPacketFrame(
|
||||
from: number,
|
||||
pos: Partial<P.Mesh.Position>,
|
||||
pos: { latitudeI?: number; longitudeI?: number },
|
||||
): Uint8Array {
|
||||
const data = create(P.Mesh.DataSchema, {
|
||||
portnum: P.Portnums.PortNum.POSITION_APP,
|
||||
@@ -80,7 +38,6 @@ function positionPacketFrame(
|
||||
);
|
||||
}
|
||||
|
||||
const KAMIL_NUM = 123456789;
|
||||
// inbound text message: TEXT_MESSAGE_APP packet with UTF-8 in Data.payload
|
||||
function textPacketFrame(
|
||||
from: number,
|
||||
@@ -138,19 +95,6 @@ function routingFrame(
|
||||
),
|
||||
);
|
||||
}
|
||||
function kamilNodeInfo(): Partial<P.Mesh.NodeInfo> {
|
||||
return {
|
||||
user: {
|
||||
id: '!kamil',
|
||||
longName: 'Kamil SP8MK/P',
|
||||
shortName: 'KK',
|
||||
hwModel: P.Mesh.HardwareModel.TBEAM,
|
||||
},
|
||||
position: { latitudeI: 521049637, longitudeI: 209833152, altitude: 123 },
|
||||
lastHeard: 1758000000,
|
||||
deviceMetrics: { batteryLevel: 87 },
|
||||
};
|
||||
}
|
||||
|
||||
function channelFrame(
|
||||
index: number,
|
||||
|
||||
Reference in New Issue
Block a user