#include "privacy_http_sdk/src/lib.rs.h"
#include "../cpp/did_nostr.hpp"
#include <iostream>
#include <unordered_map>
#include <thread>
#include <nlohmann/json.hpp>
#include <pybind11/pybind11.h>
#include <pybind11/embed.h>
#include <httplib.h>
#include <fstream>
#include <string>
using json = nlohmann::json;
namespace py = pybind11;
std::string run_stable_diffusion(const std::string& prompt, int width, int height, int steps) {
py::scoped_interpreter guard{};
try {
auto module = py::module_::import("sys");
module.attr("path").attr("append")(".");
std::string code = R"(
import torch
from diffusers import StableDiffusionPipeline
import base64
from io import BytesIO
from PIL import Image
def generate_image(prompt, width, height, steps):
pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16,
use_auth_token=False
).to("cuda" if torch.cuda.is_available() else "cpu")
image = pipe(
prompt,
width=width,
height=height,
num_inference_steps=steps
).images[0]
buffered = BytesIO()
image.save(buffered, format="PNG")
return base64.b64encode(buffered.getvalue()).decode("utf-8")
)";
auto locals = py::dict();
py::exec(code, py::globals(), locals);
auto generate_image = locals["generate_image"];
return generate_image(prompt, width, height, steps).cast<std::string>();
} catch (const py::error_already_set& e) {
throw std::runtime_error("Python error: " + std::string(e.what()));
}
}
json process_mcp_message(const json& message) {
try {
std::string message_type = message.at("message_type").get<std::string>();
std::string sender = message.at("sender").get<std::string>();
json payload = message.at("payload");
if (message_type == "command") {
std::string action = payload.at("action").get<std::string>();
std::string data = payload.at("data").get<std::string>();
return {
{"status", "success"},
{"response", "Received command from " + sender + ": " + action + ", data: " + data},
{"message_id", "123"} };
} else if (message_type == "query") {
return {
{"status", "success"},
{"response", "Query processed for " + sender},
{"message_id", "124"}
};
} else {
return {
{"status", "error"},
{"response", "Unknown message_type: " + message_type},
{"message_id", "0"}
};
}
} catch (const std::exception& e) {
return {
{"status", "error"},
{"response", "Invalid MCP message: " + std::string(e.what())},
{"message_id", "0"}
};
}
}
void start_api_server() {
httplib::Server svr;
svr.Post("/txt2img", [](const httplib::Request& req, httplib::Response& res) {
try {
json payload = json::parse(req.body);
std::string prompt = payload["prompt"].get<std::string>();
int width = payload["width"].get<int>();
int height = payload["height"].get<int>();
int steps = payload["steps"].get<int>();
if (prompt.find("<script") != std::string::npos || prompt.find("..") != std::string::npos) {
res.set_content("Invalid prompt", "text/plain");
res.status = 400;
return;
}
std::string image_base64 = run_stable_diffusion(prompt, width, height, steps);
json response = {{"image", image_base64}};
res.set_content(response.dump(), "application/json");
} catch (const std::exception& e) {
res.set_content("Error: " + std::string(e.what()), "text/plain");
res.status = 500;
}
});
svr.Post("/mcp", [](const httplib::Request& req, httplib::Response& res) {
try {
json message = json::parse(req.body);
json response = process_mcp_message(message);
res.set_content(response.dump(), "application/json");
} catch (const std::exception& e) {
json error = {
{"status", "error"},
{"response", "Failed to process MCP message: " + std::string(e.what())},
{"message_id", "0"}
};
res.set_content(error.dump(), "application/json");
res.status = 400;
}
});
std::cout << "Starting API server on http://127.0.0.1:8080" << std::endl;
std::cout << "MCP endpoint available at http://127.0.0.1:8080/mcp" << std::endl;
svr.listen("127.0.0.1", 8080);
}
namespace privacy_http_sdk {
}
class PrivacyServer {
private:
http_listener listener;
const std::string base_url = "http://localhost:3000";
json::value getAgentCard() {
json::value card;
card[U("name")] = json::value::string(U("PrivacyServerCPP"));
card[U("description")] = json::value::string(U("Privacy-focused HTTP server with A2A support"));
card[U("url")] = json::value::string(U(base_url));
card[U("version")] = json::value::string(U("1.0.0"));
json::value capabilities;
capabilities[U("streaming")] = json::value::boolean(false);
capabilities[U("pushNotifications")] = json::value::boolean(false);
capabilities[U("stateTransitionHistory")] = json::value::boolean(false);
card[U("capabilities")] = capabilities;
return card;
}
json::value createErrorResponse(int id, int code, const std::string& message) {
json::value error;
error[U("code")] = json::value::number(code);
error[U("message")] = json::value::string(U(message));
json::value response;
response[U("jsonrpc")] = json::value::string(U("2.0"));
response[U("error")] = error;
response[U("id")] = json::value::number(id);
return response;
}
public:
PrivacyServer(const std::string& url) : listener(U(url)) {
listener.support(methods::GET, [this](http_request request) {
auto path = request.relative_uri().to_string();
if (path == "/.well-known/agent.json") {
request.reply(status_codes::OK, getAgentCard());
return;
}
if (path == "/") {
json::value response;
response[U("message")] = json::value::string(U("Privacy-focused HTTP server with A2A support"));
request.reply(status_codes::OK, response);
return;
}
request.reply(status_codes::NotFound);
});
listener.support(methods::POST, [this](http_request request) {
if (request.relative_uri().to_string() != "/") {
request.reply(status_codes::NotFound);
return;
}
request.extract_json().then([request, this](json::value body) {
try {
if (!body.has_field(U("jsonrpc")) || body[U("jsonrpc")].as_string() != "2.0" ||
!body.has_field(U("id")) || !body.has_field(U("method")) || !body.has_field(U("params"))) {
request.reply(status_codes::BadRequest,
createErrorResponse(body.has_field(U("id")) ? body[U("id")].as_integer() : 0,
-32600, "Invalid Request"));
return;
}
auto headers = request.headers();
bool identity_verified = false;
std::string verified_did = "none";
if (headers.has(U("X-DID")) && headers.has(U("X-Signature"))) {
try {
using namespace http_privacy::did_nostr;
std::string did_str = utility::conversions::to_utf8string(headers[U("X-DID")]);
std::string sig_hex = utility::conversions::to_utf8string(headers[U("X-Signature")]);
auto did_obj = DidNostr::from_str(did_str);
auto signature = NostrSignature(sig_hex);
std::vector<std::pair<std::string, std::string>> req_headers;
for (const auto& header_pair : headers) {
req_headers.push_back({
utility::conversions::to_utf8string(header_pair.first),
utility::conversions::to_utf8string(header_pair.second)
});
}
std::string canonical_message = RequestCanonicalizer::canonicalize(
utility::conversions::to_utf8string(request.method()),
utility::conversions::to_utf8string(request.relative_uri().path()),
req_headers,
utility::conversions::to_utf8string(request.body()) );
auto result = NostrVerifier::verify(did_obj.pubkey(), canonical_message, signature);
auto result = NostrVerifier::verify(did_obj.pubkey(), message, signature);
if (result.is_valid()) {
identity_verified = true;
verified_did = did_str;
}
} catch (...) {
}
}
std::string method = body[U("method")].as_string();
int id = body[U("id")].as_integer();
if (method == "tasks/send") {
auto params = body[U("params")];
std::string text = "No text provided";
if (params.has_field(U("message")) && params[U("message")].has_field(U("parts")) &&
params[U("message")][U("parts")].is_array() &&
params[U("message")][U("parts")].as_array().size() > 0 &&
params[U("message")][U("parts")][0].has_field(U("text"))) {
text = params[U("message")][U("parts")][0][U("text")].as_string();
}
json::value response;
response[U("jsonrpc")] = json::value::string(U("2.0"));
response[U("id")] = json::value::number(id);
json::value result;
result[U("id")] = json::value::string(
params.has_field(U("id")) ? params[U("id")].as_string() :
"task-" + std::to_string(std::time(nullptr)));
json::value status;
status[U("state")] = json::value::string(U("completed"));
status[U("timestamp")] = json::value::string(U("2025-05-09T00:00:00Z")); result[U("status")] = status;
json::value artifacts = json::value::array();
json::value artifact;
json::value parts = json::value::array();
json::value part;
part[U("type")] = json::value::string(U("text"));
part[U("text")] = json::value::string(U("Processed: " + text + " (Verified: " + verified_did + ")"));
parts[0] = part;
artifact[U("parts")] = parts;
artifact[U("index")] = json::value::number(0);
artifacts[0] = artifact;
result[U("artifacts")] = artifacts;
response[U("result")] = result;
request.reply(status_codes::OK, response);
} else {
request.reply(status_codes::BadRequest,
createErrorResponse(id, -32601, "Method not found"));
}
} catch (const std::exception& e) {
request.reply(status_codes::InternalError);
}
});
});
}
void start() {
try {
listener.open().wait();
std::cout << "Server is running on " << base_url << std::endl;
} catch (const std::exception& e) {
std::cerr << "Error starting server: " << e.what() << std::endl;
}
}
};
int main() {
std::thread a2a_thread([]() {
PrivacyServer server("http://localhost:3000");
server.start();
});
std::thread server_thread(start_api_server);
std::this_thread::sleep_for(std::chrono::seconds(2));
auto client = privacy_http_sdk::new_http_client();
std::cout << "PrivacyHttpSdk Version: " << PRIVACY_HTTP_SDK_VERSION << std::endl;
try {
std::string mcp_url = "http://127.0.0.1:8080/mcp";
std::unordered_map<std::string, std::string> headers = {
{"Content-Type", "application/json"}
};
json mcp_message = {
{"message_type", "command"},
{"sender", "test_client"},
{"payload", {
{"action", "test_action"},
{"data", "test_data"}
}}
};
std::string mcp_body = mcp_message.dump();
auto mcp_response = client->post(mcp_url, headers, mcp_body);
std::cout << "MCP Response: " << mcp_response << std::endl;
} catch (const std::exception& e) {
std::cerr << "MCP Error: " << e.what() << std::endl;
}
std::unordered_map<std::string, std::string> headers = {
{"Authorization", "Bearer YOUR_API_KEY"},
{"Content-Type", "application/json"}
};
std::vector<std::string> urls = {
"https://api.openai.com/v1/models",
"https://api.gemini.google.com/v1/models",
"https://api.deepseek.com",
"https://bedrock-runtime.us-east-1.amazonaws.com",
"https://api.x.ai/v1/models",
"https://api.x.ai/v1",
"https://api.anthropic.com/v1/models",
"https://api.moonshot.ai/v1",
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions",
"https://api.anthropic.com/v1/messages",
"http://localhost:11434/v1"
};
for (const auto& url : urls) {
try {
auto response = client->get(url, headers);
std::cout << "GET Response from " << url << ": " << response << std::endl;
} catch (const std::exception& e) {
std::cerr << "GET Error from " << url << ": " << e.what() << std::endl;
}
}
try {
std::string body = R"({"prompt": "Hello, world!", "max_tokens": 5})";
auto response = client->post("https://api.openai.com/v1/completions", headers, body);
std::cout << "POST Response: " << response << std::endl;
} catch (const std::exception& e) {
std::cerr << "POST Error: " << e.what() << std::endl;
}
try {
client->generate_image("A serene landscape", 512, 512, 50, "output.png");
std::cout << "Image saved to output.png" << std::endl;
} catch (const std::exception& e) {
std::cerr << "Stable Diffusion Error: " << e.what() << std::endl;
}
a2a_thread.detach();
server_thread.join();
return 0;
}