index.js•9.16 kB
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
const zod_1 = require("zod");
const dns_resolver_js_1 = require("./dns-resolver.js");
const schemas_js_1 = require("./tools/schemas.js");
const config_js_1 = require("./utils/config.js");
const logger_js_1 = require("./utils/logger.js");
const configManager = new config_js_1.ConfigManager();
const logger = new logger_js_1.Logger(configManager.getLoggingConfig()?.level || 'info', configManager.getLoggingConfig()?.file);
const server = new index_js_1.Server({
name: 'dns-mcp-server',
version: '1.0.0',
}, {
capabilities: {
tools: {},
},
});
const dnsResolver = new dns_resolver_js_1.DnsResolver(configManager.getDnsConfig());
const TOOLS = [
{
name: 'dns_lookup',
description: 'Perform DNS lookup for a domain to retrieve various record types (A, AAAA, MX, TXT, etc.)',
inputSchema: {
type: 'object',
properties: {
domain: {
type: 'string',
description: 'The domain name to lookup'
},
recordType: {
type: 'string',
enum: ['A', 'AAAA', 'CNAME', 'MX', 'TXT', 'NS', 'SOA', 'PTR', 'SRV', 'CAA'],
default: 'A',
description: 'The type of DNS record to query'
},
useCustomServer: {
type: 'boolean',
description: 'Use custom DNS server if configured'
},
timeout: {
type: 'number',
description: 'Query timeout in milliseconds'
}
},
required: ['domain']
}
},
{
name: 'reverse_dns',
description: 'Perform reverse DNS lookup to find the hostname for an IP address',
inputSchema: {
type: 'object',
properties: {
ipAddress: {
type: 'string',
description: 'The IP address to perform reverse lookup on'
},
timeout: {
type: 'number',
description: 'Query timeout in milliseconds'
}
},
required: ['ipAddress']
}
},
{
name: 'batch_dns',
description: 'Perform multiple DNS lookups in a single operation',
inputSchema: {
type: 'object',
properties: {
queries: {
type: 'array',
items: {
type: 'object',
properties: {
domain: {
type: 'string'
},
recordTypes: {
type: 'array',
items: {
type: 'string',
enum: ['A', 'AAAA', 'CNAME', 'MX', 'TXT', 'NS', 'SOA', 'PTR', 'SRV', 'CAA']
}
}
},
required: ['domain', 'recordTypes']
},
description: 'Array of DNS queries to perform'
},
parallel: {
type: 'boolean',
default: true,
description: 'Execute queries in parallel'
},
timeout: {
type: 'number',
description: 'Query timeout per request'
}
},
required: ['queries']
}
},
{
name: 'dns_trace',
description: 'Trace the DNS resolution path from root servers to the final result',
inputSchema: {
type: 'object',
properties: {
domain: {
type: 'string',
description: 'The domain to trace DNS resolution path'
},
recordType: {
type: 'string',
enum: ['A', 'AAAA', 'CNAME', 'MX', 'TXT', 'NS', 'SOA', 'PTR', 'SRV', 'CAA'],
default: 'A',
description: 'The record type to trace'
}
},
required: ['domain']
}
}
];
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
return {
tools: TOOLS
};
});
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
try {
const { name, arguments: args } = request.params;
switch (name) {
case 'dns_lookup': {
const input = schemas_js_1.DnsLookupSchema.parse(args);
logger.info(`DNS lookup request for ${input.domain} (${input.recordType})`);
const result = await dnsResolver.lookup(input.domain, input.recordType, input.timeout);
logger.debug('DNS lookup result', result);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2)
}
]
};
}
case 'reverse_dns': {
const input = schemas_js_1.ReverseDnsSchema.parse(args);
logger.info(`Reverse DNS lookup for ${input.ipAddress}`);
const hostnames = await dnsResolver.reverseLookup(input.ipAddress);
logger.debug('Reverse DNS result', hostnames);
return {
content: [
{
type: 'text',
text: JSON.stringify({
ipAddress: input.ipAddress,
hostnames,
timestamp: new Date().toISOString()
}, null, 2)
}
]
};
}
case 'batch_dns': {
const input = schemas_js_1.BatchDnsSchema.parse(args);
const startTime = Date.now();
const { results, errors } = await dnsResolver.batchLookup(input.queries.map(q => ({
domain: q.domain,
recordTypes: q.recordTypes
})), input.parallel);
return {
content: [
{
type: 'text',
text: JSON.stringify({
results,
errors,
totalTime: Date.now() - startTime,
timestamp: new Date().toISOString()
}, null, 2)
}
]
};
}
case 'dns_trace': {
const input = schemas_js_1.DnsTraceSchema.parse(args);
const trace = await dnsResolver.traceDns(input.domain, input.recordType);
return {
content: [
{
type: 'text',
text: JSON.stringify({
domain: input.domain,
recordType: input.recordType,
trace,
timestamp: new Date().toISOString()
}, null, 2)
}
]
};
}
default:
throw new Error(`Unknown tool: ${name}`);
}
}
catch (error) {
if (error instanceof zod_1.z.ZodError) {
logger.error('Validation error', error.errors);
return {
content: [
{
type: 'text',
text: `Validation error: ${JSON.stringify(error.errors, null, 2)}`
}
],
isError: true
};
}
logger.error('Tool execution error', error);
return {
content: [
{
type: 'text',
text: `Error: ${error.message || 'An unknown error occurred'}`
}
],
isError: true
};
}
});
async function main() {
const transport = new stdio_js_1.StdioServerTransport();
await server.connect(transport);
logger.info('DNS MCP Server started successfully');
}
main().catch((error) => {
logger.error('Failed to start DNS MCP Server:', error);
process.exit(1);
});
//# sourceMappingURL=index.js.map