tniq-mcp 1.0.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.
Files changed (45) hide show
  1. package/.claude-plugin/plugin.json +33 -0
  2. package/.mcp.json +11 -0
  3. package/README.md +57 -0
  4. package/dist/annotations.d.ts +5 -0
  5. package/dist/annotations.js +5 -0
  6. package/dist/client.d.ts +17 -0
  7. package/dist/client.js +126 -0
  8. package/dist/config.d.ts +9 -0
  9. package/dist/config.js +24 -0
  10. package/dist/icons.d.ts +13 -0
  11. package/dist/icons.js +27 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +60 -0
  14. package/dist/knowledge.d.ts +3 -0
  15. package/dist/knowledge.js +157 -0
  16. package/dist/lib.d.ts +15 -0
  17. package/dist/lib.js +19 -0
  18. package/dist/setup.d.ts +1 -0
  19. package/dist/setup.js +370 -0
  20. package/dist/tools/bulk-port.d.ts +3 -0
  21. package/dist/tools/bulk-port.js +554 -0
  22. package/dist/tools/cnam.d.ts +3 -0
  23. package/dist/tools/cnam.js +73 -0
  24. package/dist/tools/inventory.d.ts +3 -0
  25. package/dist/tools/inventory.js +514 -0
  26. package/dist/tools/messaging.d.ts +3 -0
  27. package/dist/tools/messaging.js +871 -0
  28. package/dist/tools/port-out.d.ts +3 -0
  29. package/dist/tools/port-out.js +195 -0
  30. package/dist/tools/roc.d.ts +3 -0
  31. package/dist/tools/roc.js +317 -0
  32. package/dist/tools/soa.d.ts +3 -0
  33. package/dist/tools/soa.js +254 -0
  34. package/dist/tools/tollfree.d.ts +3 -0
  35. package/dist/tools/tollfree.js +479 -0
  36. package/dist/types.d.ts +3 -0
  37. package/dist/types.js +1 -0
  38. package/dist/utils/formatting.d.ts +14 -0
  39. package/dist/utils/formatting.js +57 -0
  40. package/dist/utils/validation.d.ts +4 -0
  41. package/dist/utils/validation.js +12 -0
  42. package/dist/version.d.ts +1 -0
  43. package/dist/version.js +15 -0
  44. package/package.json +62 -0
  45. package/postinstall.js +20 -0
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "tniq",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for TNIQ by Ringer — telecom number management, porting, toll-free, messaging, and CNAM APIs",
5
+ "author": {
6
+ "name": "Ringer",
7
+ "url": "https://ringer.tel"
8
+ },
9
+ "repository": "https://github.com/Ringer/tniq-mcp",
10
+ "homepage": "https://ringer.tel",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "mcp",
14
+ "tniq",
15
+ "ringer",
16
+ "telecom",
17
+ "porting",
18
+ "soa",
19
+ "toll-free",
20
+ "10dlc",
21
+ "messaging",
22
+ "cnam",
23
+ "npac",
24
+ "lnp"
25
+ ],
26
+ "mcpServers": "./.mcp.json",
27
+ "userConfig": {
28
+ "api_token": {
29
+ "description": "Your TNIQ API token (get one at https://ringer.tel).",
30
+ "sensitive": true
31
+ }
32
+ }
33
+ }
package/.mcp.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "mcpServers": {
3
+ "tniq": {
4
+ "command": "node",
5
+ "args": ["${CLAUDE_PLUGIN_ROOT}/dist/index.js"],
6
+ "env": {
7
+ "TNIQ_API_TOKEN": "${user_config.api_token}"
8
+ }
9
+ }
10
+ }
11
+ }
package/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # tniq-mcp
2
+
3
+ MCP server for [TNIQ by Ringer](https://ringer.tel) — telecom number management, porting, toll-free, messaging, and CNAM APIs.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx tniq-mcp setup
9
+ ```
10
+
11
+ The setup wizard will:
12
+ 1. Collect your API key
13
+ 2. Detect installed MCP clients (Claude, Cursor, Copilot, Codex, ChatGPT)
14
+ 3. Register the server automatically
15
+
16
+ ## Manual Configuration
17
+
18
+ Add to your MCP client config:
19
+
20
+ ```json
21
+ {
22
+ "mcpServers": {
23
+ "tniq": {
24
+ "command": "npx",
25
+ "args": ["-y", "tniq-mcp"],
26
+ "env": {
27
+ "TNIQ_API_TOKEN": "your-token-here"
28
+ }
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ ## Tools
35
+
36
+ | Group | Prefix | Tools | Description |
37
+ |-------|--------|-------|-------------|
38
+ | SOA Operations | `soa_` | 15 | NPAC port request lifecycle |
39
+ | Toll-Free | `tf_` | 37 | Somos TFN Registry integration |
40
+ | ROC | `roc_` | 18 | Responsible Organization Change |
41
+ | Bulk Port | `port_` | 34 | Bulk port order management |
42
+ | Port-Out Release | `port_out_` | 8 | NPAC release management |
43
+ | Messaging / 10DLC | `msg_` | 34 | TCR brand/campaign registration |
44
+ | Number Inventory | `inv_` | 30 | Number search, reserve, assign, audit |
45
+ | CNAM | `cnam_` | 3 | Caller Name ID management |
46
+
47
+ ## Environment Variables
48
+
49
+ | Variable | Description | Default |
50
+ |----------|-------------|---------|
51
+ | `TNIQ_API_TOKEN` | API bearer token | (from `~/.tniq/config.json`) |
52
+ | `TNIQ_API_BASE_URL` | API base URL | `https://soa-api.ringer.tel` |
53
+ | `TNIQ_REQUEST_TIMEOUT_MS` | Request timeout | `30000` |
54
+
55
+ ## License
56
+
57
+ MIT
@@ -0,0 +1,5 @@
1
+ export declare const READ_ONLY_ANNOTATIONS: {
2
+ readonly readOnlyHint: true;
3
+ readonly openWorldHint: false;
4
+ readonly destructiveHint: false;
5
+ };
@@ -0,0 +1,5 @@
1
+ export const READ_ONLY_ANNOTATIONS = {
2
+ readOnlyHint: true,
3
+ openWorldHint: false,
4
+ destructiveHint: false,
5
+ };
@@ -0,0 +1,17 @@
1
+ import type { Config } from "./config.js";
2
+ export declare class TniqClient {
3
+ private baseUrl;
4
+ private apiToken;
5
+ private timeoutMs;
6
+ get isAnonymous(): boolean;
7
+ constructor(config: Config);
8
+ get(path: string, params?: Record<string, string | number | boolean | undefined>): Promise<unknown>;
9
+ post(path: string, body?: unknown): Promise<unknown>;
10
+ put(path: string, body?: unknown): Promise<unknown>;
11
+ delete(path: string, params?: Record<string, string | number | boolean | undefined>, body?: unknown): Promise<unknown>;
12
+ private buildUrl;
13
+ private request;
14
+ private authHeaders;
15
+ private tryParseJson;
16
+ private describeHttpError;
17
+ }
package/dist/client.js ADDED
@@ -0,0 +1,126 @@
1
+ export class TniqClient {
2
+ baseUrl;
3
+ apiToken;
4
+ timeoutMs;
5
+ get isAnonymous() {
6
+ return this.apiToken === null;
7
+ }
8
+ constructor(config) {
9
+ this.baseUrl = config.baseUrl.replace(/\/+$/, "");
10
+ this.apiToken = config.apiToken;
11
+ this.timeoutMs = config.requestTimeoutMs;
12
+ }
13
+ async get(path, params) {
14
+ const url = this.buildUrl(path, params);
15
+ return this.request(url, { method: "GET" });
16
+ }
17
+ async post(path, body) {
18
+ const url = this.buildUrl(path);
19
+ return this.request(url, {
20
+ method: "POST",
21
+ headers: { "Content-Type": "application/json" },
22
+ body: body !== undefined ? JSON.stringify(body) : undefined,
23
+ });
24
+ }
25
+ async put(path, body) {
26
+ const url = this.buildUrl(path);
27
+ return this.request(url, {
28
+ method: "PUT",
29
+ headers: { "Content-Type": "application/json" },
30
+ body: body !== undefined ? JSON.stringify(body) : undefined,
31
+ });
32
+ }
33
+ async delete(path, params, body) {
34
+ const url = this.buildUrl(path, params);
35
+ const init = { method: "DELETE" };
36
+ if (body !== undefined) {
37
+ init.headers = { "Content-Type": "application/json" };
38
+ init.body = JSON.stringify(body);
39
+ }
40
+ return this.request(url, init);
41
+ }
42
+ buildUrl(path, params) {
43
+ const url = new URL(path, this.baseUrl);
44
+ if (params) {
45
+ for (const [key, value] of Object.entries(params)) {
46
+ if (value !== undefined) {
47
+ url.searchParams.set(key, String(value));
48
+ }
49
+ }
50
+ }
51
+ return url.toString();
52
+ }
53
+ async request(url, init) {
54
+ const controller = new AbortController();
55
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
56
+ try {
57
+ const response = await fetch(url, {
58
+ ...init,
59
+ signal: controller.signal,
60
+ headers: {
61
+ ...(init.headers || {}),
62
+ ...this.authHeaders(),
63
+ Accept: "application/json",
64
+ },
65
+ });
66
+ const text = await response.text();
67
+ if (!response.ok) {
68
+ return {
69
+ _error: true,
70
+ status: response.status,
71
+ message: this.describeHttpError(response.status),
72
+ body: this.tryParseJson(text),
73
+ };
74
+ }
75
+ return this.tryParseJson(text);
76
+ }
77
+ catch (err) {
78
+ if (err instanceof DOMException && err.name === "AbortError") {
79
+ return {
80
+ _error: true,
81
+ status: 0,
82
+ message: `Request timed out after ${this.timeoutMs}ms`,
83
+ };
84
+ }
85
+ return {
86
+ _error: true,
87
+ status: 0,
88
+ message: `Network error: ${err instanceof Error ? err.message : String(err)}`,
89
+ };
90
+ }
91
+ finally {
92
+ clearTimeout(timeout);
93
+ }
94
+ }
95
+ authHeaders() {
96
+ if (!this.apiToken)
97
+ return {};
98
+ return { Authorization: "Bearer " + this.apiToken };
99
+ }
100
+ tryParseJson(text) {
101
+ try {
102
+ return JSON.parse(text);
103
+ }
104
+ catch {
105
+ return text;
106
+ }
107
+ }
108
+ describeHttpError(status) {
109
+ switch (status) {
110
+ case 400:
111
+ return "Bad request — check parameter format";
112
+ case 401:
113
+ case 403:
114
+ return "Authentication failed — check TNIQ_API_TOKEN";
115
+ case 404:
116
+ return "Not found";
117
+ case 429:
118
+ return "Rate limit exceeded";
119
+ case 502:
120
+ case 503:
121
+ return "Service temporarily unavailable";
122
+ default:
123
+ return `HTTP ${status}`;
124
+ }
125
+ }
126
+ }
@@ -0,0 +1,9 @@
1
+ export interface Config {
2
+ baseUrl: string;
3
+ apiToken: string | null;
4
+ requestTimeoutMs: number;
5
+ }
6
+ declare const CONFIG_DIR: string;
7
+ declare const CONFIG_FILE: string;
8
+ export { CONFIG_DIR, CONFIG_FILE };
9
+ export declare function loadConfig(): Config;
package/dist/config.js ADDED
@@ -0,0 +1,24 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ const CONFIG_DIR = join(homedir(), ".tniq");
5
+ const CONFIG_FILE = join(CONFIG_DIR, "config.json");
6
+ export { CONFIG_DIR, CONFIG_FILE };
7
+ function loadTokenFromConfigFile() {
8
+ try {
9
+ const raw = readFileSync(CONFIG_FILE, "utf-8");
10
+ const config = JSON.parse(raw);
11
+ return typeof config.apiToken === "string" ? config.apiToken : null;
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ export function loadConfig() {
18
+ const apiToken = process.env.TNIQ_API_TOKEN || loadTokenFromConfigFile() || null;
19
+ return {
20
+ baseUrl: process.env.TNIQ_API_BASE_URL || "https://soa-api.ringer.tel",
21
+ apiToken,
22
+ requestTimeoutMs: parseInt(process.env.TNIQ_REQUEST_TIMEOUT_MS || "30000", 10),
23
+ };
24
+ }
@@ -0,0 +1,13 @@
1
+ export declare const ICON_LIGHT_DATA_URI: string;
2
+ export declare const ICON_DARK_DATA_URI: string;
3
+ export declare const ICONS: ({
4
+ src: string;
5
+ mimeType: string;
6
+ sizes: string[];
7
+ theme: "light";
8
+ } | {
9
+ src: string;
10
+ mimeType: string;
11
+ sizes: string[];
12
+ theme: "dark";
13
+ })[];
package/dist/icons.js ADDED
@@ -0,0 +1,27 @@
1
+ const LIGHT_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
2
+ <rect width="100" height="100" rx="16" fill="#1a1a2e"/>
3
+ <text x="50" y="62" font-family="system-ui,sans-serif" font-size="28" font-weight="700" fill="#fff" text-anchor="middle">TNIQ</text>
4
+ </svg>`;
5
+ const DARK_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
6
+ <rect width="100" height="100" rx="16" fill="#e8e8f0"/>
7
+ <text x="50" y="62" font-family="system-ui,sans-serif" font-size="28" font-weight="700" fill="#1a1a2e" text-anchor="middle">TNIQ</text>
8
+ </svg>`;
9
+ function toDataUri(svg) {
10
+ return `data:image/svg+xml;base64,${Buffer.from(svg).toString("base64")}`;
11
+ }
12
+ export const ICON_LIGHT_DATA_URI = toDataUri(LIGHT_SVG);
13
+ export const ICON_DARK_DATA_URI = toDataUri(DARK_SVG);
14
+ export const ICONS = [
15
+ {
16
+ src: toDataUri(LIGHT_SVG),
17
+ mimeType: "image/svg+xml",
18
+ sizes: ["any"],
19
+ theme: "light",
20
+ },
21
+ {
22
+ src: toDataUri(DARK_SVG),
23
+ mimeType: "image/svg+xml",
24
+ sizes: ["any"],
25
+ theme: "dark",
26
+ },
27
+ ];
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ const subcommand = process.argv[2];
3
+ if (subcommand === "setup") {
4
+ const { runSetup } = await import("./setup.js");
5
+ await runSetup();
6
+ }
7
+ else if (!subcommand && process.stdin.isTTY && !process.env.MCP_CLIENT) {
8
+ const { VERSION } = await import("./version.js");
9
+ console.log(`
10
+ tniq-mcp v${VERSION}
11
+
12
+ Usage:
13
+ tniq-mcp setup Interactive setup wizard
14
+ tniq-mcp MCP server (stdio) — used by MCP clients
15
+
16
+ Run 'tniq-mcp setup' to configure your API key and register
17
+ with your MCP clients (Claude, Cursor, Copilot, Codex, ChatGPT).
18
+ `);
19
+ }
20
+ else {
21
+ const { McpServer } = await import("@modelcontextprotocol/sdk/server/mcp.js");
22
+ const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
23
+ const { TniqClient } = await import("./client.js");
24
+ const { loadConfig } = await import("./config.js");
25
+ const { registerSoaTools } = await import("./tools/soa.js");
26
+ const { registerTollfreeTools } = await import("./tools/tollfree.js");
27
+ const { registerRocTools } = await import("./tools/roc.js");
28
+ const { registerBulkPortTools } = await import("./tools/bulk-port.js");
29
+ const { registerPortOutTools } = await import("./tools/port-out.js");
30
+ const { registerMessagingTools } = await import("./tools/messaging.js");
31
+ const { registerInventoryTools } = await import("./tools/inventory.js");
32
+ const { registerCnamTools } = await import("./tools/cnam.js");
33
+ const { registerKnowledge, TNIQ_KNOWLEDGE } = await import("./knowledge.js");
34
+ const { ICONS } = await import("./icons.js");
35
+ const { VERSION } = await import("./version.js");
36
+ const config = loadConfig();
37
+ const client = new TniqClient(config);
38
+ const server = new McpServer({
39
+ name: "tniq",
40
+ version: VERSION,
41
+ title: "TNIQ",
42
+ description: "TNIQ by Ringer — telecom number porting, toll-free, messaging, inventory, and CNAM APIs",
43
+ icons: ICONS,
44
+ websiteUrl: "https://ringer.tel",
45
+ }, {
46
+ instructions: TNIQ_KNOWLEDGE,
47
+ });
48
+ registerSoaTools(server, client);
49
+ registerTollfreeTools(server, client);
50
+ registerRocTools(server, client);
51
+ registerBulkPortTools(server, client);
52
+ registerPortOutTools(server, client);
53
+ registerMessagingTools(server, client);
54
+ registerInventoryTools(server, client);
55
+ registerCnamTools(server, client);
56
+ registerKnowledge(server);
57
+ const transport = new StdioServerTransport();
58
+ await server.connect(transport);
59
+ }
60
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerKnowledge(server: McpServer): void;
3
+ export declare const TNIQ_KNOWLEDGE = "# TNIQ API Knowledge Base\n\nYou have access to TNIQ tools for managing telecom number operations. NEVER guess carrier names, SPIDs, LRNs, port statuses, or routing data \u2014 always query the API.\n\n---\n\n## Overview\n\nTNIQ by Ringer is a telecom platform providing APIs for:\n- **SOA Operations** \u2014 NPAC port request lifecycle (create, activate, cancel, release, disconnect, conflict, IntraSP)\n- **Number Inventory** \u2014 Search, reserve, assign, release, audit, and report on telephone numbers\n- **Toll-Free** \u2014 Somos TFN Registry integration (templates, search, reserve, activate PTR, disconnect)\n- **Messaging / 10DLC** \u2014 TCR brand and campaign registration, CNP election, number assignment\n- **CNAM** \u2014 Caller Name ID management via TransUnion\n- **ROC** \u2014 Responsible Organization Change workflows for toll-free numbers\n- **Bulk Port Projects** \u2014 Bulk port order management with validation, submission, and lifecycle tracking\n- **Port-Out Releases** \u2014 NPAC release management for numbers leaving your network\n\n---\n\n## Tool Groups\n\n### SOA Operations (soa_*)\nUse for individual number porting operations against NPAC.\n\n- **soa_get_status / soa_get_spid / soa_query** \u2014 Look up current port status, SPID, or detailed query for a TN\n- **soa_get_events** \u2014 Poll for SOA events (new ports, conflicts, etc.)\n- **soa_get_activation_ready** \u2014 Find numbers ready to activate for a given SPID\n- **soa_activate** \u2014 Activate a ported number in NPAC\n- **soa_cancel** \u2014 Cancel a pending port request\n- **soa_release** \u2014 Release (approve) a port-out request\n- **soa_disconnect** \u2014 Disconnect a number from NPAC\n- **soa_create_conflict / soa_remove_conflict** \u2014 Manage port conflicts\n- **soa_intrasp** \u2014 IntraSP transfer (same carrier, different LRN)\n- **soa_create_lrn / soa_remove_lrn** \u2014 Manage LRN records in NPAC\n\n**Common flow:** Query status \u2192 Create port \u2192 Wait for FOC \u2192 Activate\n\n### Bulk Port Projects (port_*)\nUse for managing large-scale porting operations with multiple TNs.\n\n- **port_create_project** \u2014 Start a new bulk port project (requires customer_id, spid, name)\n- **port_get_details** \u2014 View TNs with pagination, filtering by validation/lifecycle status\n- **port_validate** \u2014 Trigger validation for all TNs\n- **port_submit** \u2014 Submit validated TNs to SOA\n- **port_bulk_actions** \u2014 Perform ACTIVATE, CANCEL, SUP_DDD, DELETE, REVALIDATE, SUBMIT, RESUBMIT on selected TNs\n- **port_get_lifecycle_summary** \u2014 Quick overview of where all TNs are in the porting lifecycle\n- **port_get_error_groups** \u2014 Group errors for batch resolution\n- **port_auto_fix** \u2014 Apply automatic fixes for resolvable errors\n\n**Lifecycle states:** DRAFT \u2192 VALIDATING \u2192 READY_FOR_SUBMISSION \u2192 PENDING_FOC \u2192 FOC_RECEIVED \u2192 AWAITING_DUE_DATE \u2192 READY_FOR_ACTIVATION \u2192 ACTIVATING \u2192 ACTIVATED\n\n### Port-Out Releases (port_out_*)\nUse when releasing numbers that are being ported away from your network.\n\n- **port_out_lookup** \u2014 Look up TNs to determine source SPID and subscriber data\n- **port_out_create_project** \u2014 Create a release project with TN subscriber details\n- **port_out_submit** \u2014 Submit releases to NPAC with a due date\n\n### Toll-Free (tf_*)\nUse for Somos TFN Registry operations.\n\n- **Templates** \u2014 tf_create_template, tf_update_template, tf_get_template, etc.\n- **Search & Reserve** \u2014 tf_search_spare, tf_search_and_reserve, tf_reserve\n- **Activate** \u2014 tf_activate (requires template name, effective date, service order number)\n- **Drafts** \u2014 Save work-in-progress templates before pushing to Somos\n- **Sync** \u2014 tf_start_sync to synchronize inventory with Somos\n\n**Template workflow:** Create/update template \u2192 Save draft \u2192 Push to Somos \u2192 Activate TFNs with template\n\n### ROC (roc_*)\nUse for Responsible Organization Changes on toll-free numbers.\n\n- **Outbound ROC:** roc_create_project \u2192 roc_upload_loa/roc_generate_loa \u2192 roc_submit\n- **Inbound ROC:** roc_inbound_checkout \u2192 roc_inbound_process (approve/deny per TFN) \u2192 roc_inbound_checkin\n- **roc_escalate_hdi** \u2014 Escalate stuck ROC to Somos Help Desk\n\n### Messaging / 10DLC (msg_*)\nUse for TCR brand/campaign registration and number assignment.\n\n- **Brands:** msg_create_brand \u2192 msg_get_brand (wait for vetting) \u2192 msg_link_brand (if existing TCR brand)\n- **Campaigns:** msg_create_campaign \u2192 msg_elect_cnp \u2192 msg_assign_numbers\n- **Reference data:** msg_list_verticals, msg_list_use_cases, msg_list_entity_types, msg_list_mnos, msg_list_cnps\n- **NNIDs:** Manage network node IDs for messaging routing\n\n**Brand is required before creating campaigns. Campaign must be approved before assigning numbers.**\n\n### Number Inventory (inv_*)\nUse for managing your telephone number inventory.\n\n- **inv_query** \u2014 Flexible search with query string syntax\n- **inv_aggregate** \u2014 Group and count numbers by field (state, LATA, status, etc.)\n- **inv_get_number** \u2014 Full details for a single TN\n- **inv_reserve_number / inv_assign_number / inv_release_number** \u2014 Lifecycle management\n- **inv_start_audit** \u2014 Compare inventory against NPAC to find discrepancies\n- **inv_get_map_data** \u2014 Geographic visualization data\n\n### CNAM (cnam_*)\nUse for managing Caller Name ID records.\n\n- **cnam_query** \u2014 Look up the CNAM record for a number\n- **cnam_activate** \u2014 Set or update the displayed caller name (max 15 chars)\n- **cnam_delete** \u2014 Remove a CNAM record\n\n---\n\n## Key Concepts\n\n| Term | Definition |\n|------|-----------|\n| TN | Telephone Number \u2014 always 10 digits (NPA + NXX + line) |\n| SPID | Service Provider ID \u2014 4-character alphanumeric code identifying a carrier |\n| LRN | Location Routing Number \u2014 10-digit number used for routing ported calls |\n| NPAC | Number Portability Administration Center \u2014 central database for ported numbers |\n| SOA | Service Order Administration \u2014 interface for submitting port requests to NPAC |\n| FOC | Firm Order Confirmation \u2014 carrier acknowledgment that a port will proceed |\n| DDD | Desired Due Date \u2014 when the port should activate |\n| OCN | Operating Company Number \u2014 identifies the carrier operating a switch |\n| LATA | Local Access and Transport Area \u2014 geographic region for telecom routing |\n| RespOrg | Responsible Organization \u2014 entity managing toll-free numbers in Somos |\n| ROC | Responsible Organization Change \u2014 transferring TFN management to a new RespOrg |\n| TCR | The Campaign Registry \u2014 central registry for 10DLC messaging campaigns |\n| CNP | Connectivity Partner \u2014 messaging aggregator that provides network connectivity |\n| NNID | Network Node ID \u2014 identifier for messaging routing nodes |\n| CNAM | Caller Name \u2014 the name displayed on caller ID |\n| IntraSP | Intra-Service Provider \u2014 moving a number within the same carrier to a new LRN |\n| CPR | Call Processing Record \u2014 routing rules for toll-free numbers |\n| PTR | Pointer Record \u2014 maps a toll-free number to a template/CPR |\n\n---\n\n## Common Mistakes to Avoid\n\n1. **Don't guess SPIDs or carrier names** \u2014 Use soa_get_spid or soa_query to look up the current SPID for a TN\n2. **Don't activate before FOC** \u2014 A port must receive FOC and reach its due date before activation\n3. **Don't skip validation in bulk ports** \u2014 Always run port_validate before port_submit\n4. **Don't confuse TN and LRN** \u2014 The TN is the customer-facing number; the LRN is for routing\n5. **ROC requires LOA** \u2014 Most ROC submissions need a Letter of Authorization uploaded first\n6. **TCR brand before campaign** \u2014 You must create/link a brand before creating a 10DLC campaign\n7. **CNAM is max 15 characters** \u2014 The caller name field has a strict 15-character limit\n8. **Template before toll-free activation** \u2014 TFNs must be activated with a template name and effective date\n9. **Use port_get_lifecycle_summary for quick status** \u2014 Don't fetch all TN details just to count states\n10. **Check port_get_error_groups before manual fixes** \u2014 Many errors have auto-fix available\n";
@@ -0,0 +1,157 @@
1
+ export function registerKnowledge(server) {
2
+ server.prompt("tniq-guide", "Comprehensive guide to TNIQ APIs — telecom porting, toll-free, messaging, inventory, and CNAM. Load this before answering domain questions.", () => ({
3
+ messages: [
4
+ {
5
+ role: "user",
6
+ content: {
7
+ type: "text",
8
+ text: TNIQ_KNOWLEDGE,
9
+ },
10
+ },
11
+ ],
12
+ }));
13
+ }
14
+ export const TNIQ_KNOWLEDGE = `# TNIQ API Knowledge Base
15
+
16
+ You have access to TNIQ tools for managing telecom number operations. NEVER guess carrier names, SPIDs, LRNs, port statuses, or routing data — always query the API.
17
+
18
+ ---
19
+
20
+ ## Overview
21
+
22
+ TNIQ by Ringer is a telecom platform providing APIs for:
23
+ - **SOA Operations** — NPAC port request lifecycle (create, activate, cancel, release, disconnect, conflict, IntraSP)
24
+ - **Number Inventory** — Search, reserve, assign, release, audit, and report on telephone numbers
25
+ - **Toll-Free** — Somos TFN Registry integration (templates, search, reserve, activate PTR, disconnect)
26
+ - **Messaging / 10DLC** — TCR brand and campaign registration, CNP election, number assignment
27
+ - **CNAM** — Caller Name ID management via TransUnion
28
+ - **ROC** — Responsible Organization Change workflows for toll-free numbers
29
+ - **Bulk Port Projects** — Bulk port order management with validation, submission, and lifecycle tracking
30
+ - **Port-Out Releases** — NPAC release management for numbers leaving your network
31
+
32
+ ---
33
+
34
+ ## Tool Groups
35
+
36
+ ### SOA Operations (soa_*)
37
+ Use for individual number porting operations against NPAC.
38
+
39
+ - **soa_get_status / soa_get_spid / soa_query** — Look up current port status, SPID, or detailed query for a TN
40
+ - **soa_get_events** — Poll for SOA events (new ports, conflicts, etc.)
41
+ - **soa_get_activation_ready** — Find numbers ready to activate for a given SPID
42
+ - **soa_activate** — Activate a ported number in NPAC
43
+ - **soa_cancel** — Cancel a pending port request
44
+ - **soa_release** — Release (approve) a port-out request
45
+ - **soa_disconnect** — Disconnect a number from NPAC
46
+ - **soa_create_conflict / soa_remove_conflict** — Manage port conflicts
47
+ - **soa_intrasp** — IntraSP transfer (same carrier, different LRN)
48
+ - **soa_create_lrn / soa_remove_lrn** — Manage LRN records in NPAC
49
+
50
+ **Common flow:** Query status → Create port → Wait for FOC → Activate
51
+
52
+ ### Bulk Port Projects (port_*)
53
+ Use for managing large-scale porting operations with multiple TNs.
54
+
55
+ - **port_create_project** — Start a new bulk port project (requires customer_id, spid, name)
56
+ - **port_get_details** — View TNs with pagination, filtering by validation/lifecycle status
57
+ - **port_validate** — Trigger validation for all TNs
58
+ - **port_submit** — Submit validated TNs to SOA
59
+ - **port_bulk_actions** — Perform ACTIVATE, CANCEL, SUP_DDD, DELETE, REVALIDATE, SUBMIT, RESUBMIT on selected TNs
60
+ - **port_get_lifecycle_summary** — Quick overview of where all TNs are in the porting lifecycle
61
+ - **port_get_error_groups** — Group errors for batch resolution
62
+ - **port_auto_fix** — Apply automatic fixes for resolvable errors
63
+
64
+ **Lifecycle states:** DRAFT → VALIDATING → READY_FOR_SUBMISSION → PENDING_FOC → FOC_RECEIVED → AWAITING_DUE_DATE → READY_FOR_ACTIVATION → ACTIVATING → ACTIVATED
65
+
66
+ ### Port-Out Releases (port_out_*)
67
+ Use when releasing numbers that are being ported away from your network.
68
+
69
+ - **port_out_lookup** — Look up TNs to determine source SPID and subscriber data
70
+ - **port_out_create_project** — Create a release project with TN subscriber details
71
+ - **port_out_submit** — Submit releases to NPAC with a due date
72
+
73
+ ### Toll-Free (tf_*)
74
+ Use for Somos TFN Registry operations.
75
+
76
+ - **Templates** — tf_create_template, tf_update_template, tf_get_template, etc.
77
+ - **Search & Reserve** — tf_search_spare, tf_search_and_reserve, tf_reserve
78
+ - **Activate** — tf_activate (requires template name, effective date, service order number)
79
+ - **Drafts** — Save work-in-progress templates before pushing to Somos
80
+ - **Sync** — tf_start_sync to synchronize inventory with Somos
81
+
82
+ **Template workflow:** Create/update template → Save draft → Push to Somos → Activate TFNs with template
83
+
84
+ ### ROC (roc_*)
85
+ Use for Responsible Organization Changes on toll-free numbers.
86
+
87
+ - **Outbound ROC:** roc_create_project → roc_upload_loa/roc_generate_loa → roc_submit
88
+ - **Inbound ROC:** roc_inbound_checkout → roc_inbound_process (approve/deny per TFN) → roc_inbound_checkin
89
+ - **roc_escalate_hdi** — Escalate stuck ROC to Somos Help Desk
90
+
91
+ ### Messaging / 10DLC (msg_*)
92
+ Use for TCR brand/campaign registration and number assignment.
93
+
94
+ - **Brands:** msg_create_brand → msg_get_brand (wait for vetting) → msg_link_brand (if existing TCR brand)
95
+ - **Campaigns:** msg_create_campaign → msg_elect_cnp → msg_assign_numbers
96
+ - **Reference data:** msg_list_verticals, msg_list_use_cases, msg_list_entity_types, msg_list_mnos, msg_list_cnps
97
+ - **NNIDs:** Manage network node IDs for messaging routing
98
+
99
+ **Brand is required before creating campaigns. Campaign must be approved before assigning numbers.**
100
+
101
+ ### Number Inventory (inv_*)
102
+ Use for managing your telephone number inventory.
103
+
104
+ - **inv_query** — Flexible search with query string syntax
105
+ - **inv_aggregate** — Group and count numbers by field (state, LATA, status, etc.)
106
+ - **inv_get_number** — Full details for a single TN
107
+ - **inv_reserve_number / inv_assign_number / inv_release_number** — Lifecycle management
108
+ - **inv_start_audit** — Compare inventory against NPAC to find discrepancies
109
+ - **inv_get_map_data** — Geographic visualization data
110
+
111
+ ### CNAM (cnam_*)
112
+ Use for managing Caller Name ID records.
113
+
114
+ - **cnam_query** — Look up the CNAM record for a number
115
+ - **cnam_activate** — Set or update the displayed caller name (max 15 chars)
116
+ - **cnam_delete** — Remove a CNAM record
117
+
118
+ ---
119
+
120
+ ## Key Concepts
121
+
122
+ | Term | Definition |
123
+ |------|-----------|
124
+ | TN | Telephone Number — always 10 digits (NPA + NXX + line) |
125
+ | SPID | Service Provider ID — 4-character alphanumeric code identifying a carrier |
126
+ | LRN | Location Routing Number — 10-digit number used for routing ported calls |
127
+ | NPAC | Number Portability Administration Center — central database for ported numbers |
128
+ | SOA | Service Order Administration — interface for submitting port requests to NPAC |
129
+ | FOC | Firm Order Confirmation — carrier acknowledgment that a port will proceed |
130
+ | DDD | Desired Due Date — when the port should activate |
131
+ | OCN | Operating Company Number — identifies the carrier operating a switch |
132
+ | LATA | Local Access and Transport Area — geographic region for telecom routing |
133
+ | RespOrg | Responsible Organization — entity managing toll-free numbers in Somos |
134
+ | ROC | Responsible Organization Change — transferring TFN management to a new RespOrg |
135
+ | TCR | The Campaign Registry — central registry for 10DLC messaging campaigns |
136
+ | CNP | Connectivity Partner — messaging aggregator that provides network connectivity |
137
+ | NNID | Network Node ID — identifier for messaging routing nodes |
138
+ | CNAM | Caller Name — the name displayed on caller ID |
139
+ | IntraSP | Intra-Service Provider — moving a number within the same carrier to a new LRN |
140
+ | CPR | Call Processing Record — routing rules for toll-free numbers |
141
+ | PTR | Pointer Record — maps a toll-free number to a template/CPR |
142
+
143
+ ---
144
+
145
+ ## Common Mistakes to Avoid
146
+
147
+ 1. **Don't guess SPIDs or carrier names** — Use soa_get_spid or soa_query to look up the current SPID for a TN
148
+ 2. **Don't activate before FOC** — A port must receive FOC and reach its due date before activation
149
+ 3. **Don't skip validation in bulk ports** — Always run port_validate before port_submit
150
+ 4. **Don't confuse TN and LRN** — The TN is the customer-facing number; the LRN is for routing
151
+ 5. **ROC requires LOA** — Most ROC submissions need a Letter of Authorization uploaded first
152
+ 6. **TCR brand before campaign** — You must create/link a brand before creating a 10DLC campaign
153
+ 7. **CNAM is max 15 characters** — The caller name field has a strict 15-character limit
154
+ 8. **Template before toll-free activation** — TFNs must be activated with a template name and effective date
155
+ 9. **Use port_get_lifecycle_summary for quick status** — Don't fetch all TN details just to count states
156
+ 10. **Check port_get_error_groups before manual fixes** — Many errors have auto-fix available
157
+ `;
package/dist/lib.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export { TniqClient } from "./client.js";
2
+ export type { Config } from "./config.js";
3
+ export { registerSoaTools } from "./tools/soa.js";
4
+ export { registerTollfreeTools } from "./tools/tollfree.js";
5
+ export { registerRocTools } from "./tools/roc.js";
6
+ export { registerBulkPortTools } from "./tools/bulk-port.js";
7
+ export { registerPortOutTools } from "./tools/port-out.js";
8
+ export { registerMessagingTools } from "./tools/messaging.js";
9
+ export { registerInventoryTools } from "./tools/inventory.js";
10
+ export { registerCnamTools } from "./tools/cnam.js";
11
+ export { registerKnowledge, TNIQ_KNOWLEDGE } from "./knowledge.js";
12
+ export { ICONS, ICON_LIGHT_DATA_URI, ICON_DARK_DATA_URI } from "./icons.js";
13
+ export { VERSION } from "./version.js";
14
+ export { READ_ONLY_ANNOTATIONS } from "./annotations.js";
15
+ export type { ToolRegistrar } from "./types.js";
package/dist/lib.js ADDED
@@ -0,0 +1,19 @@
1
+ // Library exports for use by remote MCP servers and other consumers
2
+ // Client
3
+ export { TniqClient } from "./client.js";
4
+ // Tool registrars
5
+ export { registerSoaTools } from "./tools/soa.js";
6
+ export { registerTollfreeTools } from "./tools/tollfree.js";
7
+ export { registerRocTools } from "./tools/roc.js";
8
+ export { registerBulkPortTools } from "./tools/bulk-port.js";
9
+ export { registerPortOutTools } from "./tools/port-out.js";
10
+ export { registerMessagingTools } from "./tools/messaging.js";
11
+ export { registerInventoryTools } from "./tools/inventory.js";
12
+ export { registerCnamTools } from "./tools/cnam.js";
13
+ // Knowledge / prompts
14
+ export { registerKnowledge, TNIQ_KNOWLEDGE } from "./knowledge.js";
15
+ // Metadata
16
+ export { ICONS, ICON_LIGHT_DATA_URI, ICON_DARK_DATA_URI } from "./icons.js";
17
+ export { VERSION } from "./version.js";
18
+ // Annotations
19
+ export { READ_ONLY_ANNOTATIONS } from "./annotations.js";
@@ -0,0 +1 @@
1
+ export declare function runSetup(): Promise<void>;