Tools are the most powerful MCP primitive. They let AI assistants execute code on your server — querying databases, calling APIs, processing files, and performing any action your application supports.
await mcp.registerTool( "calculate", description: "Perform arithmetic calculations", inputSchema: [ "expression": "string" ], handler: { args in let expr = args["expression"] as? String ?? "" // Parse and evaluate (simplified) let result = evaluate(expr) return PrismMCPToolResult( content: [.text("Result: \(result)")], isError: false ) })
Write clear, specific tool descriptions. The AI uses these to decide when and how to call your tools. A good description is the difference between a tool that gets used correctly and one that gets ignored.
await mcp.registerTool( "query_db", description: "Run a read-only SQL query against the application database", inputSchema: ["sql": "string"], handler: { args in let sql = args["sql"] as? String ?? "" // Safety: only allow SELECT guard sql.trimmingCharacters(in: .whitespaces) .uppercased().hasPrefix("SELECT") else { return PrismMCPToolResult( content: [.text("Only SELECT queries are allowed")], isError: true ) } let rows = try await db.query(sql) let output = rows.map { row in row.columns.map { "\($0.key): \($0.value)" }.joined(separator: ", ") }.joined(separator: "\n") return PrismMCPToolResult( content: [.text(output.isEmpty ? "No results" : output)], isError: false ) })
HTTP Request Tool
await mcp.registerTool( "http_get", description: "Make an HTTP GET request to a URL and return the response", inputSchema: ["url": "string"], handler: { args in let url = args["url"] as? String ?? "" let client = PrismHTTPClient() let response = try await client.get(url) let body = response.text ?? "(empty)" return PrismMCPToolResult( content: [.text("Status: \(response.statusCode)\n\n\(body)")], isError: response.statusCode >= 400 ) })
File Search Tool
await mcp.registerTool( "find_files", description: "Search for files matching a pattern in the project directory", inputSchema: ["pattern": "string", "directory": "string"], handler: { args in let pattern = args["pattern"] as? String ?? "*" let dir = args["directory"] as? String ?? "." let fm = FileManager.default let enumerator = fm.enumerator(atPath: dir) var matches: [String] = [] while let file = enumerator?.nextObject() as? String { if file.contains(pattern) { matches.append(file) } } return PrismMCPToolResult( content: [.text(matches.isEmpty ? "No files found" : matches.joined(separator: "\n"))], isError: false ) })